From c85b0ba71b5a55647b01de9d345e46896979033d Mon Sep 17 00:00:00 2001 From: "chase@chromium.org" Date: Tue, 21 Dec 2010 00:23:26 +0000 Subject: Revert "Move the NPAPI files from webkit/glue/plugins to webkit/plugins/npapi" Manually reverting r69755, which broke the tree. BUG=none TEST=none TBR=dmaclach@chromium.org Review URL: http://codereview.chromium.org/5998002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69771 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/app/framework.order | 14 +- chrome/browser/automation/automation_provider.cc | 1 + .../automation/testing_automation_provider.cc | 17 +- chrome/browser/dom_ui/plugins_ui.cc | 5 +- chrome/browser/gtk/content_setting_bubble_gtk.cc | 4 +- chrome/browser/hang_monitor/hung_plugin_action.cc | 6 +- chrome/browser/metrics/metrics_log.cc | 8 +- chrome/browser/metrics/metrics_log.h | 15 +- chrome/browser/metrics/metrics_service.cc | 19 +- chrome/browser/metrics/metrics_service.h | 9 +- .../browser/mock_plugin_exceptions_table_model.cc | 4 +- .../browser/mock_plugin_exceptions_table_model.h | 7 +- chrome/browser/plugin_carbon_interpose_mac.cc | 14 +- chrome/browser/plugin_data_remover.cc | 21 +- chrome/browser/plugin_data_remover.h | 2 +- chrome/browser/plugin_exceptions_table_model.cc | 6 +- chrome/browser/plugin_exceptions_table_model.h | 5 +- .../plugin_exceptions_table_model_unittest.cc | 18 +- chrome/browser/plugin_installer.cc | 6 +- chrome/browser/plugin_process_host.cc | 2 +- chrome/browser/plugin_process_host.h | 10 +- chrome/browser/plugin_service.cc | 50 +- chrome/browser/plugin_service.h | 8 +- chrome/browser/plugin_service_browsertest.cc | 12 +- chrome/browser/plugin_service_unittest.cc | 1 + chrome/browser/plugin_updater.cc | 45 +- chrome/browser/plugin_updater.h | 15 +- .../accelerated_surface_container_mac.cc | 4 +- .../accelerated_surface_container_mac.h | 6 +- .../accelerated_surface_container_manager_mac.cc | 4 +- .../accelerated_surface_container_manager_mac.h | 7 +- .../renderer_host/buffered_resource_handler.cc | 14 +- .../browser/renderer_host/render_message_filter.cc | 32 +- .../browser/renderer_host/render_message_filter.h | 7 +- chrome/browser/renderer_host/render_widget_host.cc | 2 +- .../renderer_host/render_widget_host_view.h | 7 +- .../renderer_host/render_widget_host_view_gtk.cc | 4 +- .../renderer_host/render_widget_host_view_gtk.h | 6 +- .../renderer_host/render_widget_host_view_mac.h | 2 +- .../renderer_host/render_widget_host_view_mac.mm | 12 +- .../render_widget_host_view_mac_unittest.mm | 4 +- .../renderer_host/render_widget_host_view_views.cc | 2 +- .../renderer_host/render_widget_host_view_views.h | 2 +- .../renderer_host/render_widget_host_view_win.cc | 19 +- .../renderer_host/render_widget_host_view_win.h | 2 +- .../renderer_host/test/test_render_view_host.h | 2 +- chrome/browser/tab_contents/tab_contents.cc | 6 +- .../cocoa/table_model_array_controller_unittest.mm | 24 +- chrome/common/chrome_plugin_lib.cc | 4 +- chrome/common/default_plugin.cc | 9 +- chrome/common/gpu_plugin.cc | 14 +- chrome/common/render_messages.cc | 34 +- chrome/common/render_messages.h | 23 +- chrome/common/render_messages_internal.h | 10 +- chrome/common/render_messages_params.h | 4 +- chrome/default_plugin/DEPS | 1 - chrome/default_plugin/plugin_impl_gtk.cc | 4 +- chrome/default_plugin/plugin_impl_mac.mm | 4 +- chrome/default_plugin/plugin_impl_win.cc | 13 +- chrome/plugin/DEPS | 2 +- chrome/plugin/chrome_plugin_host.cc | 6 +- chrome/plugin/npobject_proxy.cc | 6 +- chrome/plugin/npobject_stub.cc | 4 +- chrome/plugin/npobject_util.cc | 4 +- chrome/plugin/plugin_channel.cc | 8 +- chrome/plugin/plugin_interpose_util_mac.mm | 18 +- chrome/plugin/plugin_thread.cc | 10 +- chrome/plugin/plugin_thread.h | 2 +- .../webplugin_accelerated_surface_proxy_mac.h | 4 +- chrome/plugin/webplugin_delegate_stub.cc | 19 +- chrome/plugin/webplugin_delegate_stub.h | 6 +- chrome/plugin/webplugin_proxy.cc | 10 +- chrome/plugin/webplugin_proxy.h | 24 +- chrome/renderer/blocked_plugin.cc | 14 +- chrome/renderer/blocked_plugin.h | 18 +- chrome/renderer/pepper_devices.cc | 4 +- chrome/renderer/pepper_devices_browsertest.cc | 21 +- chrome/renderer/pepper_plugin_delegate_impl.cc | 2 +- chrome/renderer/pepper_scrollbar_widget.cc | 2 +- chrome/renderer/pepper_widget.cc | 14 +- chrome/renderer/render_process_impl.cc | 4 +- chrome/renderer/render_view.cc | 46 +- chrome/renderer/render_view.h | 21 +- chrome/renderer/render_widget.cc | 4 +- chrome/renderer/render_widget.h | 8 +- chrome/renderer/renderer_glue.cc | 3 +- chrome/renderer/webplugin_delegate_pepper.cc | 39 +- chrome/renderer/webplugin_delegate_pepper.h | 22 +- chrome/renderer/webplugin_delegate_proxy.cc | 17 +- chrome/renderer/webplugin_delegate_proxy.h | 20 +- chrome/test/plugin/plugin_test.cpp | 7 +- webkit/glue/plugins/DEPS | 9 + .../plugins/carbon_plugin_window_tracker_mac.cc | 55 + .../plugins/carbon_plugin_window_tracker_mac.h | 53 + .../plugins/coregraphics_private_symbols_mac.h | 27 + webkit/glue/plugins/default_plugin_shared.h | 31 + webkit/glue/plugins/gtk_plugin_container.cc | 85 ++ webkit/glue/plugins/gtk_plugin_container.h | 26 + .../glue/plugins/gtk_plugin_container_manager.cc | 155 +++ webkit/glue/plugins/gtk_plugin_container_manager.h | 57 + webkit/glue/plugins/npapi_extension_thunk.cc | 551 ++++++++ webkit/glue/plugins/npapi_extension_thunk.h | 23 + webkit/glue/plugins/plugin_constants_win.h | 41 + webkit/glue/plugins/plugin_group.cc | 407 ++++++ webkit/glue/plugins/plugin_group.h | 205 +++ webkit/glue/plugins/plugin_group_unittest.cc | 224 ++++ webkit/glue/plugins/plugin_host.cc | 1111 +++++++++++++++ webkit/glue/plugins/plugin_host.h | 63 + webkit/glue/plugins/plugin_instance.cc | 680 ++++++++++ webkit/glue/plugins/plugin_instance.h | 375 ++++++ webkit/glue/plugins/plugin_instance_mac.mm | 133 ++ webkit/glue/plugins/plugin_lib.cc | 349 +++++ webkit/glue/plugins/plugin_lib.h | 120 ++ webkit/glue/plugins/plugin_lib_mac.mm | 348 +++++ webkit/glue/plugins/plugin_lib_posix.cc | 256 ++++ webkit/glue/plugins/plugin_lib_unittest.cc | 152 +++ webkit/glue/plugins/plugin_lib_win.cc | 46 + webkit/glue/plugins/plugin_list.cc | 781 +++++++++++ webkit/glue/plugins/plugin_list.h | 332 ++++- webkit/glue/plugins/plugin_list_mac.mm | 109 ++ webkit/glue/plugins/plugin_list_posix.cc | 270 ++++ webkit/glue/plugins/plugin_list_win.cc | 410 ++++++ webkit/glue/plugins/plugin_stream.cc | 258 ++++ webkit/glue/plugins/plugin_stream.h | 156 +++ webkit/glue/plugins/plugin_stream_posix.cc | 74 + webkit/glue/plugins/plugin_stream_url.cc | 130 ++ webkit/glue/plugins/plugin_stream_url.h | 65 + webkit/glue/plugins/plugin_stream_win.cc | 97 ++ webkit/glue/plugins/plugin_string_stream.cc | 37 + webkit/glue/plugins/plugin_string_stream.h | 39 + webkit/glue/plugins/plugin_stubs.cc | 30 + .../glue/plugins/plugin_web_event_converter_mac.h | 60 + .../glue/plugins/plugin_web_event_converter_mac.mm | 359 +++++ .../glue/plugins/quickdraw_drawing_manager_mac.cc | 154 +++ .../glue/plugins/quickdraw_drawing_manager_mac.h | 83 ++ webkit/glue/plugins/test/Info.plist | 46 + webkit/glue/plugins/test/npapi_constants.cc | 10 + webkit/glue/plugins/test/npapi_constants.h | 19 + webkit/glue/plugins/test/npapi_test.cc | 122 ++ webkit/glue/plugins/test/npapi_test.def | 6 + webkit/glue/plugins/test/npapi_test.rc | 102 ++ webkit/glue/plugins/test/plugin_arguments_test.cc | 69 + webkit/glue/plugins/test/plugin_arguments_test.h | 43 + webkit/glue/plugins/test/plugin_client.cc | 240 ++++ webkit/glue/plugins/test/plugin_client.h | 45 + .../test/plugin_create_instance_in_paint.cc | 78 ++ .../plugins/test/plugin_create_instance_in_paint.h | 33 + .../test/plugin_delete_plugin_in_stream_test.cc | 45 + .../test/plugin_delete_plugin_in_stream_test.h | 30 + .../test/plugin_get_javascript_url2_test.cc | 134 ++ .../plugins/test/plugin_get_javascript_url2_test.h | 38 + .../plugins/test/plugin_get_javascript_url_test.cc | 218 +++ .../plugins/test/plugin_get_javascript_url_test.h | 47 + webkit/glue/plugins/test/plugin_geturl_test.cc | 414 ++++++ webkit/glue/plugins/test/plugin_geturl_test.h | 61 + .../plugins/test/plugin_javascript_open_popup.cc | 103 ++ .../plugins/test/plugin_javascript_open_popup.h | 47 + webkit/glue/plugins/test/plugin_new_fails_test.cc | 18 + webkit/glue/plugins/test/plugin_new_fails_test.h | 21 + .../plugins/test/plugin_npobject_lifetime_test.cc | 174 +++ .../plugins/test/plugin_npobject_lifetime_test.h | 82 ++ .../plugins/test/plugin_npobject_proxy_test.cc | 51 + .../glue/plugins/test/plugin_npobject_proxy_test.h | 27 + webkit/glue/plugins/test/plugin_private_test.cc | 57 + webkit/glue/plugins/test/plugin_private_test.h | 25 + .../plugins/test/plugin_schedule_timer_test.cc | 116 ++ .../glue/plugins/test/plugin_schedule_timer_test.h | 68 + webkit/glue/plugins/test/plugin_setup_test.cc | 22 + webkit/glue/plugins/test/plugin_setup_test.h | 24 + webkit/glue/plugins/test/plugin_test.cc | 155 +++ webkit/glue/plugins/test/plugin_test.h | 134 ++ webkit/glue/plugins/test/plugin_test_factory.cc | 104 ++ webkit/glue/plugins/test/plugin_test_factory.h | 22 + .../plugins/test/plugin_thread_async_call_test.cc | 117 ++ .../plugins/test/plugin_thread_async_call_test.h | 39 + .../glue/plugins/test/plugin_window_size_test.cc | 55 + webkit/glue/plugins/test/plugin_window_size_test.h | 24 + webkit/glue/plugins/test/plugin_windowed_test.cc | 150 +++ webkit/glue/plugins/test/plugin_windowed_test.h | 33 + webkit/glue/plugins/test/plugin_windowless_test.cc | 261 ++++ webkit/glue/plugins/test/plugin_windowless_test.h | 35 + webkit/glue/plugins/test/resource.h | 15 + webkit/glue/plugins/url_request_info_unittest.cc | 249 ++++ webkit/glue/plugins/webplugin.cc | 31 + webkit/glue/plugins/webplugin.h | 200 +++ .../glue/plugins/webplugin_2d_device_delegate.cc | 53 + webkit/glue/plugins/webplugin_2d_device_delegate.h | 43 + .../glue/plugins/webplugin_3d_device_delegate.cc | 110 ++ webkit/glue/plugins/webplugin_3d_device_delegate.h | 71 + .../plugins/webplugin_accelerated_surface_mac.h | 44 + .../plugins/webplugin_audio_device_delegate.cc | 50 + .../glue/plugins/webplugin_audio_device_delegate.h | 42 + webkit/glue/plugins/webplugin_delegate.cc | 40 + webkit/glue/plugins/webplugin_delegate.h | 166 +++ webkit/glue/plugins/webplugin_delegate_impl.cc | 304 +++++ webkit/glue/plugins/webplugin_delegate_impl.h | 511 +++++++ webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 767 +++++++++++ webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 1145 ++++++++++++++++ webkit/glue/plugins/webplugin_delegate_impl_win.cc | 1410 +++++++++++++++++++ webkit/glue/plugins/webplugin_file_delegate.cc | 17 + webkit/glue/plugins/webplugin_file_delegate.h | 33 + webkit/glue/plugins/webplugin_impl.cc | 1393 +++++++++++++++++++ webkit/glue/plugins/webplugin_impl.h | 330 +++++ webkit/glue/plugins/webplugin_impl_unittest.cc | 232 ++++ webkit/glue/plugins/webplugin_page_delegate.h | 69 + webkit/glue/plugins/webplugin_print_delegate.cc | 26 + webkit/glue/plugins/webplugin_print_delegate.h | 43 + webkit/glue/plugins/webplugininfo.cc | 44 + webkit/glue/plugins/webplugininfo.h | 60 + webkit/glue/plugins/webview_plugin.cc | 235 ++++ webkit/glue/plugins/webview_plugin.h | 142 ++ webkit/glue/webkit_glue.gypi | 146 +- webkit/glue/webkit_glue.h | 10 +- webkit/glue/webkitclient_impl.cc | 10 +- webkit/plugins/npapi/DEPS | 11 - .../npapi/carbon_plugin_window_tracker_mac.cc | 62 - .../npapi/carbon_plugin_window_tracker_mac.h | 59 - .../npapi/coregraphics_private_symbols_mac.h | 27 - webkit/plugins/npapi/default_plugin_shared.h | 37 - webkit/plugins/npapi/gtk_plugin_container.cc | 91 -- webkit/plugins/npapi/gtk_plugin_container.h | 32 - .../plugins/npapi/gtk_plugin_container_manager.cc | 161 --- .../plugins/npapi/gtk_plugin_container_manager.h | 61 - webkit/plugins/npapi/npapi_extension_thunk.cc | 553 -------- webkit/plugins/npapi/npapi_extension_thunk.h | 25 - webkit/plugins/npapi/plugin_constants_win.cc | 28 - webkit/plugins/npapi/plugin_constants_win.h | 45 - webkit/plugins/npapi/plugin_group.cc | 413 ------ webkit/plugins/npapi/plugin_group.h | 211 --- webkit/plugins/npapi/plugin_group_unittest.cc | 228 ---- webkit/plugins/npapi/plugin_host.cc | 1122 ---------------- webkit/plugins/npapi/plugin_host.h | 65 - webkit/plugins/npapi/plugin_instance.cc | 681 ---------- webkit/plugins/npapi/plugin_instance.h | 375 ------ webkit/plugins/npapi/plugin_instance_mac.mm | 134 -- webkit/plugins/npapi/plugin_lib.cc | 351 ----- webkit/plugins/npapi/plugin_lib.h | 122 -- webkit/plugins/npapi/plugin_lib_mac.mm | 350 ----- webkit/plugins/npapi/plugin_lib_posix.cc | 257 ---- webkit/plugins/npapi/plugin_lib_unittest.cc | 158 --- webkit/plugins/npapi/plugin_lib_win.cc | 48 - webkit/plugins/npapi/plugin_list.cc | 785 ----------- webkit/plugins/npapi/plugin_list.h | 339 ----- webkit/plugins/npapi/plugin_list_mac.mm | 110 -- webkit/plugins/npapi/plugin_list_posix.cc | 272 ---- webkit/plugins/npapi/plugin_list_win.cc | 413 ------ webkit/plugins/npapi/plugin_stream.cc | 260 ---- webkit/plugins/npapi/plugin_stream.h | 152 --- webkit/plugins/npapi/plugin_stream_posix.cc | 76 -- webkit/plugins/npapi/plugin_stream_url.cc | 132 -- webkit/plugins/npapi/plugin_stream_url.h | 66 - webkit/plugins/npapi/plugin_stream_win.cc | 99 -- webkit/plugins/npapi/plugin_string_stream.cc | 39 - webkit/plugins/npapi/plugin_string_stream.h | 42 - .../plugins/npapi/plugin_web_event_converter_mac.h | 66 - .../npapi/plugin_web_event_converter_mac.mm | 365 ----- .../plugins/npapi/quickdraw_drawing_manager_mac.cc | 160 --- .../plugins/npapi/quickdraw_drawing_manager_mac.h | 89 -- webkit/plugins/npapi/test/Info.plist | 46 - webkit/plugins/npapi/test/npapi_constants.cc | 12 - webkit/plugins/npapi/test/npapi_constants.h | 22 - webkit/plugins/npapi/test/npapi_test.cc | 122 -- webkit/plugins/npapi/test/npapi_test.def | 6 - webkit/plugins/npapi/test/npapi_test.rc | 102 -- webkit/plugins/npapi/test/plugin_arguments_test.cc | 69 - webkit/plugins/npapi/test/plugin_arguments_test.h | 43 - webkit/plugins/npapi/test/plugin_client.cc | 240 ---- webkit/plugins/npapi/test/plugin_client.h | 45 - .../npapi/test/plugin_create_instance_in_paint.cc | 78 -- .../npapi/test/plugin_create_instance_in_paint.h | 33 - .../test/plugin_delete_plugin_in_stream_test.cc | 45 - .../test/plugin_delete_plugin_in_stream_test.h | 30 - .../npapi/test/plugin_get_javascript_url2_test.cc | 134 -- .../npapi/test/plugin_get_javascript_url2_test.h | 38 - .../npapi/test/plugin_get_javascript_url_test.cc | 218 --- .../npapi/test/plugin_get_javascript_url_test.h | 47 - webkit/plugins/npapi/test/plugin_geturl_test.cc | 414 ------ webkit/plugins/npapi/test/plugin_geturl_test.h | 61 - .../npapi/test/plugin_javascript_open_popup.cc | 103 -- .../npapi/test/plugin_javascript_open_popup.h | 47 - webkit/plugins/npapi/test/plugin_new_fails_test.cc | 18 - webkit/plugins/npapi/test/plugin_new_fails_test.h | 21 - .../npapi/test/plugin_npobject_lifetime_test.cc | 174 --- .../npapi/test/plugin_npobject_lifetime_test.h | 82 -- .../npapi/test/plugin_npobject_proxy_test.cc | 51 - .../npapi/test/plugin_npobject_proxy_test.h | 27 - webkit/plugins/npapi/test/plugin_private_test.cc | 57 - webkit/plugins/npapi/test/plugin_private_test.h | 25 - .../npapi/test/plugin_schedule_timer_test.cc | 116 -- .../npapi/test/plugin_schedule_timer_test.h | 68 - webkit/plugins/npapi/test/plugin_setup_test.cc | 22 - webkit/plugins/npapi/test/plugin_setup_test.h | 24 - webkit/plugins/npapi/test/plugin_test.cc | 155 --- webkit/plugins/npapi/test/plugin_test.h | 134 -- webkit/plugins/npapi/test/plugin_test_factory.cc | 104 -- webkit/plugins/npapi/test/plugin_test_factory.h | 22 - .../npapi/test/plugin_thread_async_call_test.cc | 117 -- .../npapi/test/plugin_thread_async_call_test.h | 39 - .../plugins/npapi/test/plugin_window_size_test.cc | 55 - .../plugins/npapi/test/plugin_window_size_test.h | 24 - webkit/plugins/npapi/test/plugin_windowed_test.cc | 150 --- webkit/plugins/npapi/test/plugin_windowed_test.h | 33 - .../plugins/npapi/test/plugin_windowless_test.cc | 261 ---- webkit/plugins/npapi/test/plugin_windowless_test.h | 35 - webkit/plugins/npapi/test/resource.h | 15 - webkit/plugins/npapi/webplugin.cc | 33 - webkit/plugins/npapi/webplugin.h | 202 --- .../plugins/npapi/webplugin_2d_device_delegate.cc | 55 - .../plugins/npapi/webplugin_2d_device_delegate.h | 45 - .../plugins/npapi/webplugin_3d_device_delegate.cc | 111 -- .../plugins/npapi/webplugin_3d_device_delegate.h | 73 - .../npapi/webplugin_accelerated_surface_mac.h | 46 - .../npapi/webplugin_audio_device_delegate.cc | 51 - .../npapi/webplugin_audio_device_delegate.h | 44 - webkit/plugins/npapi/webplugin_delegate.cc | 41 - webkit/plugins/npapi/webplugin_delegate.h | 168 --- webkit/plugins/npapi/webplugin_delegate_impl.cc | 307 ----- webkit/plugins/npapi/webplugin_delegate_impl.h | 515 ------- .../plugins/npapi/webplugin_delegate_impl_gtk.cc | 773 ----------- .../plugins/npapi/webplugin_delegate_impl_mac.mm | 1149 ---------------- .../plugins/npapi/webplugin_delegate_impl_win.cc | 1413 -------------------- webkit/plugins/npapi/webplugin_file_delegate.cc | 19 - webkit/plugins/npapi/webplugin_file_delegate.h | 35 - webkit/plugins/npapi/webplugin_impl.cc | 1396 ------------------- webkit/plugins/npapi/webplugin_impl.h | 335 ----- webkit/plugins/npapi/webplugin_impl_unittest.cc | 234 ---- webkit/plugins/npapi/webplugin_page_delegate.h | 71 - webkit/plugins/npapi/webplugin_print_delegate.cc | 28 - webkit/plugins/npapi/webplugin_print_delegate.h | 45 - webkit/plugins/npapi/webplugininfo.cc | 50 - webkit/plugins/npapi/webplugininfo.h | 66 - webkit/plugins/npapi/webview_plugin.cc | 241 ---- webkit/plugins/npapi/webview_plugin.h | 148 -- webkit/plugins/plugin_switches.cc | 6 - webkit/plugins/plugin_switches.h | 6 - webkit/plugins/ppapi/url_request_info_unittest.cc | 249 ---- webkit/support/platform_support_mac.mm | 4 +- webkit/support/test_webplugin_page_delegate.h | 14 +- webkit/support/webkit_support.cc | 16 +- webkit/support/webkit_support_glue.cc | 11 +- .../tools/test_shell/mac/test_webview_delegate.mm | 11 +- webkit/tools/test_shell/test_shell.cc | 27 +- webkit/tools/test_shell/test_shell.gypi | 120 +- webkit/tools/test_shell/test_shell_mac.mm | 4 +- webkit/tools/test_shell/test_webview_delegate.cc | 27 +- webkit/tools/test_shell/test_webview_delegate.h | 39 +- .../tools/test_shell/test_webview_delegate_gtk.cc | 17 +- .../tools/test_shell/test_webview_delegate_win.cc | 12 +- webkit/tools/test_shell/webview_host.h | 6 +- webkit/tools/test_shell/webview_host_gtk.cc | 2 +- 350 files changed, 21327 insertions(+), 21726 deletions(-) create mode 100644 webkit/glue/plugins/DEPS create mode 100644 webkit/glue/plugins/carbon_plugin_window_tracker_mac.cc create mode 100644 webkit/glue/plugins/carbon_plugin_window_tracker_mac.h create mode 100644 webkit/glue/plugins/coregraphics_private_symbols_mac.h create mode 100644 webkit/glue/plugins/default_plugin_shared.h create mode 100644 webkit/glue/plugins/gtk_plugin_container.cc create mode 100644 webkit/glue/plugins/gtk_plugin_container.h create mode 100644 webkit/glue/plugins/gtk_plugin_container_manager.cc create mode 100644 webkit/glue/plugins/gtk_plugin_container_manager.h create mode 100644 webkit/glue/plugins/npapi_extension_thunk.cc create mode 100644 webkit/glue/plugins/npapi_extension_thunk.h create mode 100644 webkit/glue/plugins/plugin_constants_win.h create mode 100644 webkit/glue/plugins/plugin_group.cc create mode 100644 webkit/glue/plugins/plugin_group.h create mode 100644 webkit/glue/plugins/plugin_group_unittest.cc create mode 100644 webkit/glue/plugins/plugin_host.cc create mode 100644 webkit/glue/plugins/plugin_host.h create mode 100644 webkit/glue/plugins/plugin_instance.cc create mode 100644 webkit/glue/plugins/plugin_instance.h create mode 100644 webkit/glue/plugins/plugin_instance_mac.mm create mode 100644 webkit/glue/plugins/plugin_lib.cc create mode 100644 webkit/glue/plugins/plugin_lib.h create mode 100644 webkit/glue/plugins/plugin_lib_mac.mm create mode 100644 webkit/glue/plugins/plugin_lib_posix.cc create mode 100644 webkit/glue/plugins/plugin_lib_unittest.cc create mode 100644 webkit/glue/plugins/plugin_lib_win.cc create mode 100644 webkit/glue/plugins/plugin_list.cc create mode 100644 webkit/glue/plugins/plugin_list_mac.mm create mode 100644 webkit/glue/plugins/plugin_list_posix.cc create mode 100644 webkit/glue/plugins/plugin_list_win.cc create mode 100644 webkit/glue/plugins/plugin_stream.cc create mode 100644 webkit/glue/plugins/plugin_stream.h create mode 100644 webkit/glue/plugins/plugin_stream_posix.cc create mode 100644 webkit/glue/plugins/plugin_stream_url.cc create mode 100644 webkit/glue/plugins/plugin_stream_url.h create mode 100644 webkit/glue/plugins/plugin_stream_win.cc create mode 100644 webkit/glue/plugins/plugin_string_stream.cc create mode 100644 webkit/glue/plugins/plugin_string_stream.h create mode 100644 webkit/glue/plugins/plugin_stubs.cc create mode 100644 webkit/glue/plugins/plugin_web_event_converter_mac.h create mode 100644 webkit/glue/plugins/plugin_web_event_converter_mac.mm create mode 100644 webkit/glue/plugins/quickdraw_drawing_manager_mac.cc create mode 100644 webkit/glue/plugins/quickdraw_drawing_manager_mac.h create mode 100644 webkit/glue/plugins/test/Info.plist create mode 100644 webkit/glue/plugins/test/npapi_constants.cc create mode 100644 webkit/glue/plugins/test/npapi_constants.h create mode 100644 webkit/glue/plugins/test/npapi_test.cc create mode 100644 webkit/glue/plugins/test/npapi_test.def create mode 100644 webkit/glue/plugins/test/npapi_test.rc create mode 100644 webkit/glue/plugins/test/plugin_arguments_test.cc create mode 100644 webkit/glue/plugins/test/plugin_arguments_test.h create mode 100644 webkit/glue/plugins/test/plugin_client.cc create mode 100644 webkit/glue/plugins/test/plugin_client.h create mode 100644 webkit/glue/plugins/test/plugin_create_instance_in_paint.cc create mode 100644 webkit/glue/plugins/test/plugin_create_instance_in_paint.h create mode 100644 webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.cc create mode 100644 webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h create mode 100644 webkit/glue/plugins/test/plugin_get_javascript_url2_test.cc create mode 100644 webkit/glue/plugins/test/plugin_get_javascript_url2_test.h create mode 100644 webkit/glue/plugins/test/plugin_get_javascript_url_test.cc create mode 100644 webkit/glue/plugins/test/plugin_get_javascript_url_test.h create mode 100644 webkit/glue/plugins/test/plugin_geturl_test.cc create mode 100644 webkit/glue/plugins/test/plugin_geturl_test.h create mode 100644 webkit/glue/plugins/test/plugin_javascript_open_popup.cc create mode 100644 webkit/glue/plugins/test/plugin_javascript_open_popup.h create mode 100644 webkit/glue/plugins/test/plugin_new_fails_test.cc create mode 100644 webkit/glue/plugins/test/plugin_new_fails_test.h create mode 100644 webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc create mode 100644 webkit/glue/plugins/test/plugin_npobject_lifetime_test.h create mode 100644 webkit/glue/plugins/test/plugin_npobject_proxy_test.cc create mode 100644 webkit/glue/plugins/test/plugin_npobject_proxy_test.h create mode 100644 webkit/glue/plugins/test/plugin_private_test.cc create mode 100644 webkit/glue/plugins/test/plugin_private_test.h create mode 100644 webkit/glue/plugins/test/plugin_schedule_timer_test.cc create mode 100644 webkit/glue/plugins/test/plugin_schedule_timer_test.h create mode 100644 webkit/glue/plugins/test/plugin_setup_test.cc create mode 100644 webkit/glue/plugins/test/plugin_setup_test.h create mode 100644 webkit/glue/plugins/test/plugin_test.cc create mode 100644 webkit/glue/plugins/test/plugin_test.h create mode 100644 webkit/glue/plugins/test/plugin_test_factory.cc create mode 100644 webkit/glue/plugins/test/plugin_test_factory.h create mode 100644 webkit/glue/plugins/test/plugin_thread_async_call_test.cc create mode 100644 webkit/glue/plugins/test/plugin_thread_async_call_test.h create mode 100644 webkit/glue/plugins/test/plugin_window_size_test.cc create mode 100644 webkit/glue/plugins/test/plugin_window_size_test.h create mode 100644 webkit/glue/plugins/test/plugin_windowed_test.cc create mode 100644 webkit/glue/plugins/test/plugin_windowed_test.h create mode 100644 webkit/glue/plugins/test/plugin_windowless_test.cc create mode 100644 webkit/glue/plugins/test/plugin_windowless_test.h create mode 100644 webkit/glue/plugins/test/resource.h create mode 100644 webkit/glue/plugins/url_request_info_unittest.cc create mode 100644 webkit/glue/plugins/webplugin.cc create mode 100644 webkit/glue/plugins/webplugin.h create mode 100644 webkit/glue/plugins/webplugin_2d_device_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_2d_device_delegate.h create mode 100644 webkit/glue/plugins/webplugin_3d_device_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_3d_device_delegate.h create mode 100644 webkit/glue/plugins/webplugin_accelerated_surface_mac.h create mode 100644 webkit/glue/plugins/webplugin_audio_device_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_audio_device_delegate.h create mode 100644 webkit/glue/plugins/webplugin_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_delegate.h create mode 100644 webkit/glue/plugins/webplugin_delegate_impl.cc create mode 100644 webkit/glue/plugins/webplugin_delegate_impl.h create mode 100644 webkit/glue/plugins/webplugin_delegate_impl_gtk.cc create mode 100644 webkit/glue/plugins/webplugin_delegate_impl_mac.mm create mode 100644 webkit/glue/plugins/webplugin_delegate_impl_win.cc create mode 100644 webkit/glue/plugins/webplugin_file_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_file_delegate.h create mode 100644 webkit/glue/plugins/webplugin_impl.cc create mode 100644 webkit/glue/plugins/webplugin_impl.h create mode 100644 webkit/glue/plugins/webplugin_impl_unittest.cc create mode 100644 webkit/glue/plugins/webplugin_page_delegate.h create mode 100644 webkit/glue/plugins/webplugin_print_delegate.cc create mode 100644 webkit/glue/plugins/webplugin_print_delegate.h create mode 100644 webkit/glue/plugins/webplugininfo.cc create mode 100644 webkit/glue/plugins/webplugininfo.h create mode 100644 webkit/glue/plugins/webview_plugin.cc create mode 100644 webkit/glue/plugins/webview_plugin.h delete mode 100644 webkit/plugins/npapi/DEPS delete mode 100644 webkit/plugins/npapi/carbon_plugin_window_tracker_mac.cc delete mode 100644 webkit/plugins/npapi/carbon_plugin_window_tracker_mac.h delete mode 100644 webkit/plugins/npapi/coregraphics_private_symbols_mac.h delete mode 100644 webkit/plugins/npapi/default_plugin_shared.h delete mode 100644 webkit/plugins/npapi/gtk_plugin_container.cc delete mode 100644 webkit/plugins/npapi/gtk_plugin_container.h delete mode 100644 webkit/plugins/npapi/gtk_plugin_container_manager.cc delete mode 100644 webkit/plugins/npapi/gtk_plugin_container_manager.h delete mode 100644 webkit/plugins/npapi/npapi_extension_thunk.cc delete mode 100644 webkit/plugins/npapi/npapi_extension_thunk.h delete mode 100644 webkit/plugins/npapi/plugin_constants_win.cc delete mode 100644 webkit/plugins/npapi/plugin_constants_win.h delete mode 100644 webkit/plugins/npapi/plugin_group.cc delete mode 100644 webkit/plugins/npapi/plugin_group.h delete mode 100644 webkit/plugins/npapi/plugin_group_unittest.cc delete mode 100644 webkit/plugins/npapi/plugin_host.cc delete mode 100644 webkit/plugins/npapi/plugin_host.h delete mode 100644 webkit/plugins/npapi/plugin_instance.cc delete mode 100644 webkit/plugins/npapi/plugin_instance.h delete mode 100644 webkit/plugins/npapi/plugin_instance_mac.mm delete mode 100644 webkit/plugins/npapi/plugin_lib.cc delete mode 100644 webkit/plugins/npapi/plugin_lib.h delete mode 100644 webkit/plugins/npapi/plugin_lib_mac.mm delete mode 100644 webkit/plugins/npapi/plugin_lib_posix.cc delete mode 100644 webkit/plugins/npapi/plugin_lib_unittest.cc delete mode 100644 webkit/plugins/npapi/plugin_lib_win.cc delete mode 100644 webkit/plugins/npapi/plugin_list.cc delete mode 100644 webkit/plugins/npapi/plugin_list.h delete mode 100644 webkit/plugins/npapi/plugin_list_mac.mm delete mode 100644 webkit/plugins/npapi/plugin_list_posix.cc delete mode 100644 webkit/plugins/npapi/plugin_list_win.cc delete mode 100644 webkit/plugins/npapi/plugin_stream.cc delete mode 100644 webkit/plugins/npapi/plugin_stream.h delete mode 100644 webkit/plugins/npapi/plugin_stream_posix.cc delete mode 100644 webkit/plugins/npapi/plugin_stream_url.cc delete mode 100644 webkit/plugins/npapi/plugin_stream_url.h delete mode 100644 webkit/plugins/npapi/plugin_stream_win.cc delete mode 100644 webkit/plugins/npapi/plugin_string_stream.cc delete mode 100644 webkit/plugins/npapi/plugin_string_stream.h delete mode 100644 webkit/plugins/npapi/plugin_web_event_converter_mac.h delete mode 100644 webkit/plugins/npapi/plugin_web_event_converter_mac.mm delete mode 100644 webkit/plugins/npapi/quickdraw_drawing_manager_mac.cc delete mode 100644 webkit/plugins/npapi/quickdraw_drawing_manager_mac.h delete mode 100644 webkit/plugins/npapi/test/Info.plist delete mode 100644 webkit/plugins/npapi/test/npapi_constants.cc delete mode 100644 webkit/plugins/npapi/test/npapi_constants.h delete mode 100644 webkit/plugins/npapi/test/npapi_test.cc delete mode 100644 webkit/plugins/npapi/test/npapi_test.def delete mode 100644 webkit/plugins/npapi/test/npapi_test.rc delete mode 100644 webkit/plugins/npapi/test/plugin_arguments_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_arguments_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_client.cc delete mode 100644 webkit/plugins/npapi/test/plugin_client.h delete mode 100644 webkit/plugins/npapi/test/plugin_create_instance_in_paint.cc delete mode 100644 webkit/plugins/npapi/test/plugin_create_instance_in_paint.h delete mode 100644 webkit/plugins/npapi/test/plugin_delete_plugin_in_stream_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_delete_plugin_in_stream_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_get_javascript_url2_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_get_javascript_url2_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_get_javascript_url_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_get_javascript_url_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_geturl_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_geturl_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_javascript_open_popup.cc delete mode 100644 webkit/plugins/npapi/test/plugin_javascript_open_popup.h delete mode 100644 webkit/plugins/npapi/test/plugin_new_fails_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_new_fails_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_npobject_lifetime_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_npobject_lifetime_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_npobject_proxy_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_npobject_proxy_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_private_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_private_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_schedule_timer_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_schedule_timer_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_setup_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_setup_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_test_factory.cc delete mode 100644 webkit/plugins/npapi/test/plugin_test_factory.h delete mode 100644 webkit/plugins/npapi/test/plugin_thread_async_call_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_thread_async_call_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_window_size_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_window_size_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_windowed_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_windowed_test.h delete mode 100644 webkit/plugins/npapi/test/plugin_windowless_test.cc delete mode 100644 webkit/plugins/npapi/test/plugin_windowless_test.h delete mode 100644 webkit/plugins/npapi/test/resource.h delete mode 100644 webkit/plugins/npapi/webplugin.cc delete mode 100644 webkit/plugins/npapi/webplugin.h delete mode 100644 webkit/plugins/npapi/webplugin_2d_device_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_2d_device_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_3d_device_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_3d_device_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_accelerated_surface_mac.h delete mode 100644 webkit/plugins/npapi/webplugin_audio_device_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_audio_device_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_delegate_impl.cc delete mode 100644 webkit/plugins/npapi/webplugin_delegate_impl.h delete mode 100644 webkit/plugins/npapi/webplugin_delegate_impl_gtk.cc delete mode 100644 webkit/plugins/npapi/webplugin_delegate_impl_mac.mm delete mode 100644 webkit/plugins/npapi/webplugin_delegate_impl_win.cc delete mode 100644 webkit/plugins/npapi/webplugin_file_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_file_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_impl.cc delete mode 100644 webkit/plugins/npapi/webplugin_impl.h delete mode 100644 webkit/plugins/npapi/webplugin_impl_unittest.cc delete mode 100644 webkit/plugins/npapi/webplugin_page_delegate.h delete mode 100644 webkit/plugins/npapi/webplugin_print_delegate.cc delete mode 100644 webkit/plugins/npapi/webplugin_print_delegate.h delete mode 100644 webkit/plugins/npapi/webplugininfo.cc delete mode 100644 webkit/plugins/npapi/webplugininfo.h delete mode 100644 webkit/plugins/npapi/webview_plugin.cc delete mode 100644 webkit/plugins/npapi/webview_plugin.h delete mode 100644 webkit/plugins/ppapi/url_request_info_unittest.cc diff --git a/chrome/app/framework.order b/chrome/app/framework.order index 4ac4c01..71cb3d3 100644 --- a/chrome/app/framework.order +++ b/chrome/app/framework.order @@ -30,13 +30,13 @@ __ZN22mac_plugin_interposing31NotifyBrowserOfPluginHideWindowEj6CGRect __ZN22mac_plugin_interposing28NotifyPluginOfSetThemeCursorEPvm __ZN22mac_plugin_interposing23NotifyPluginOfSetCursorEPvPK6Cursor __ZN22mac_plugin_interposing23GetPluginWindowHasFocusEPv -__ZN6webkit5npapi25CarbonPluginWindowTrackerC1Ev -__ZN6webkit5npapi25CarbonPluginWindowTrackerC2Ev -__ZN6webkit5npapi25CarbonPluginWindowTracker14SharedInstanceEv -__ZN6webkit5npapi25CarbonPluginWindowTracker28CreateDummyWindowForDelegateEPv -__ZNK6webkit5npapi25CarbonPluginWindowTracker25GetDelegateForDummyWindowEP15OpaqueWindowPtr -__ZNK6webkit5npapi25CarbonPluginWindowTracker25GetDummyWindowForDelegateEPv -__ZN6webkit5npapi25CarbonPluginWindowTracker29DestroyDummyWindowForDelegateEPvP15OpaqueWindowPtr +__ZN25CarbonPluginWindowTrackerC1Ev +__ZN25CarbonPluginWindowTrackerC2Ev +__ZN25CarbonPluginWindowTracker14SharedInstanceEv +__ZN25CarbonPluginWindowTracker28CreateDummyWindowForDelegateEPv +__ZNK25CarbonPluginWindowTracker25GetDelegateForDummyWindowEP15OpaqueWindowPtr +__ZNK25CarbonPluginWindowTracker25GetDummyWindowForDelegateEPv +__ZN25CarbonPluginWindowTracker29DestroyDummyWindowForDelegateEPvP15OpaqueWindowPtr __ZN7WebCore22narrowPrecisionToFloatIdEEfT_ __ZN7WebCore24narrowPrecisionToCGFloatIdEEfT_ __ZnwmPv diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 4108f69..be9e2d2 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -102,6 +102,7 @@ #include "chrome/browser/automation/ui_controls.h" #include "views/event.h" #include "webkit/glue/password_form.h" +#include "webkit/glue/plugins/plugin_list.h" #if defined(OS_WIN) #include "chrome/browser/external_tab_container_win.h" diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 129dc8f..fcc609f 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -75,7 +75,7 @@ #include "net/base/cookie_store.h" #include "net/url_request/url_request_context.h" #include "views/event.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { @@ -2993,11 +2993,10 @@ void TestingAutomationProvider::GetPluginsInfo( Browser* browser, DictionaryValue* args, IPC::Message* reply_message) { - std::vector plugins; - webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins); + std::vector plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); ListValue* items = new ListValue; - for (std::vector::const_iterator it = - plugins.begin(); + for (std::vector::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { DictionaryValue* item = new DictionaryValue; @@ -3008,7 +3007,7 @@ void TestingAutomationProvider::GetPluginsInfo( item->SetBoolean("enabled", it->enabled); // Add info about mime types. ListValue* mime_types = new ListValue(); - for (std::vector::const_iterator type_it = + for (std::vector::const_iterator type_it = it->mime_types.begin(); type_it != it->mime_types.end(); ++type_it) { @@ -3047,8 +3046,7 @@ void TestingAutomationProvider::EnablePlugin(Browser* browser, if (!args->GetString("path", &path)) { reply.SendError("path not specified."); return; - } else if (!webkit::npapi::PluginList::Singleton()->EnablePlugin( - FilePath(path))) { + } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) { reply.SendError(StringPrintf("Could not enable plugin for path %s.", path.c_str())); return; @@ -3067,8 +3065,7 @@ void TestingAutomationProvider::DisablePlugin(Browser* browser, if (!args->GetString("path", &path)) { reply.SendError("path not specified."); return; - } else if (!webkit::npapi::PluginList::Singleton()->DisablePlugin( - FilePath(path))) { + } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) { reply.SendError(StringPrintf("Could not disable plugin for path %s.", path.c_str())); return; diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc index aaf59f1..6746fdd 100644 --- a/chrome/browser/dom_ui/plugins_ui.cc +++ b/chrome/browser/dom_ui/plugins_ui.cc @@ -32,7 +32,7 @@ #include "grit/browser_resources.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { @@ -223,8 +223,7 @@ void PluginsDOMHandler::HandleEnablePluginMessage(const ListValue* args) { plugin_updater->EnablePluginGroup(enable, group_name); if (enable) { // See http://crbug.com/50105 for background. - string16 adobereader = ASCIIToUTF16( - webkit::npapi::PluginGroup::kAdobeReaderGroupName); + string16 adobereader = ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName); string16 internalpdf = ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName); if (group_name == adobereader) { plugin_updater->EnablePluginGroup(false, internalpdf); diff --git a/chrome/browser/gtk/content_setting_bubble_gtk.cc b/chrome/browser/gtk/content_setting_bubble_gtk.cc index f8c36f0..a53d69c 100644 --- a/chrome/browser/gtk/content_setting_bubble_gtk.cc +++ b/chrome/browser/gtk/content_setting_bubble_gtk.cc @@ -27,7 +27,7 @@ #include "gfx/gtk_util.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { @@ -109,7 +109,7 @@ void ContentSettingBubbleGtk::BuildBubble() { for (std::set::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { std::string name = UTF16ToUTF8( - webkit::npapi::PluginList::Singleton()->GetPluginGroupName(*it)); + NPAPI::PluginList::Singleton()->GetPluginGroupName(*it)); if (name.empty()) name = *it; diff --git a/chrome/browser/hang_monitor/hung_plugin_action.cc b/chrome/browser/hang_monitor/hung_plugin_action.cc index 9b719ca..8399464 100644 --- a/chrome/browser/hang_monitor/hung_plugin_action.cc +++ b/chrome/browser/hang_monitor/hung_plugin_action.cc @@ -12,7 +12,7 @@ #include "chrome/browser/platform_util.h" #include "chrome/common/logging_chrome.h" #include "grit/generated_resources.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) { } @@ -122,8 +122,8 @@ bool HungPluginAction::GetPluginName(HWND plugin_window, // we have gone too far. return false; } - if (webkit::npapi::WebPluginDelegateImpl::GetPluginNameFromWindow( - window_to_check, plugin_name)) { + if (WebPluginDelegateImpl::GetPluginNameFromWindow(window_to_check, + plugin_name)) { return true; } window_to_check = GetParent(window_to_check); diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc index bf54134..d0a1f01 100644 --- a/chrome/browser/metrics/metrics_log.cc +++ b/chrome/browser/metrics/metrics_log.cc @@ -25,7 +25,6 @@ #include "chrome/common/logging_chrome.h" #include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" -#include "webkit/plugins/npapi/webplugininfo.h" #define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name) @@ -238,13 +237,12 @@ void MetricsLog::WriteRealtimeStabilityAttributes(PrefService* pref) { } void MetricsLog::WritePluginList( - const std::vector& plugin_list) { + const std::vector& plugin_list) { DCHECK(!locked_); OPEN_ELEMENT_FOR_SCOPE("plugins"); - for (std::vector::const_iterator iter = - plugin_list.begin(); + for (std::vector::const_iterator iter = plugin_list.begin(); iter != plugin_list.end(); ++iter) { OPEN_ELEMENT_FOR_SCOPE("plugin"); @@ -264,7 +262,7 @@ void MetricsLog::WriteInstallElement() { } void MetricsLog::RecordEnvironment( - const std::vector& plugin_list, + const std::vector& plugin_list, const DictionaryValue* profile_metrics) { DCHECK(!locked_); diff --git a/chrome/browser/metrics/metrics_log.h b/chrome/browser/metrics/metrics_log.h index 0cb8b29..8f35705 100644 --- a/chrome/browser/metrics/metrics_log.h +++ b/chrome/browser/metrics/metrics_log.h @@ -12,18 +12,13 @@ #include "base/basictypes.h" #include "chrome/common/metrics_helpers.h" #include "chrome/common/page_transition_types.h" +#include "webkit/glue/plugins/webplugininfo.h" struct AutocompleteLog; class DictionaryValue; class GURL; class PrefService; -namespace webkit { -namespace npapi { -struct WebPluginInfo; -} -} - class MetricsLog : public MetricsLogBase { public: // Creates a new metrics log @@ -40,9 +35,8 @@ class MetricsLog : public MetricsLogBase { // profile_metrics, if non-null, gives a dictionary of all profile metrics // that are to be recorded. Each value in profile_metrics should be a // dictionary giving the metrics for the profile. - void RecordEnvironment( - const std::vector& plugin_list, - const DictionaryValue* profile_metrics); + void RecordEnvironment(const std::vector& plugin_list, + const DictionaryValue* profile_metrics); // Records the input text, available choices, and selected entry when the // user uses the Omnibox to open a URL. @@ -86,8 +80,7 @@ class MetricsLog : public MetricsLogBase { void WriteRealtimeStabilityAttributes(PrefService* pref); // Writes the list of installed plugins. - void WritePluginList( - const std::vector& plugin_list); + void WritePluginList(const std::vector& plugin_list); // Within the profile group, write basic install info including appversion. void WriteInstallElement(); diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index 5e1af15..5aea04a 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -184,8 +184,8 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugininfo.h" #include "libxml/xmlwriter.h" // TODO(port): port browser_distribution.h. @@ -336,9 +336,8 @@ class MetricsMemoryDetails : public MemoryDetails { class MetricsService::InitTaskComplete : public Task { public: - explicit InitTaskComplete( - const std::string& hardware_class, - const std::vector& plugins) + explicit InitTaskComplete(const std::string& hardware_class, + const std::vector& plugins) : hardware_class_(hardware_class), plugins_(plugins) {} virtual void Run() { @@ -348,7 +347,7 @@ class MetricsService::InitTaskComplete : public Task { private: std::string hardware_class_; - std::vector plugins_; + std::vector plugins_; }; class MetricsService::InitTask : public Task { @@ -357,12 +356,12 @@ class MetricsService::InitTask : public Task { : callback_loop_(callback_loop) {} virtual void Run() { - std::vector plugins; - webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins); + std::vector plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); std::string hardware_class; // Empty string by default. #if defined(OS_CHROMEOS) chromeos::SystemLibrary* system_library = - chromeos::CrosLibrary::Get()->GetSystemLibrary(); + chromeos::CrosLibrary::Get()->GetSystemLibrary(); system_library->GetMachineStatistic("hardware_class", &hardware_class); #endif // OS_CHROMEOS callback_loop_->PostTask(FROM_HERE, new InitTaskComplete( @@ -802,7 +801,7 @@ void MetricsService::InitializeMetricsState() { void MetricsService::OnInitTaskComplete( const std::string& hardware_class, - const std::vector& plugins) { + const std::vector& plugins) { DCHECK(state_ == INIT_TASK_SCHEDULED); hardware_class_ = hardware_class; plugins_ = plugins; diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h index fa15a12..f1cfbb2 100644 --- a/chrome/browser/metrics/metrics_service.h +++ b/chrome/browser/metrics/metrics_service.h @@ -33,12 +33,7 @@ class HistogramSynchronizer; class MetricsLogBase; class PrefService; class TemplateURLModel; - -namespace webkit { -namespace npapi { struct WebPluginInfo; -} -} // Forward declaration of the xmlNode to avoid having tons of gyp files // needing to depend on the libxml third party lib. @@ -160,7 +155,7 @@ class MetricsService : public NotificationObserver, // Callback to let us know that the init task is done. void OnInitTaskComplete( const std::string& hardware_class, - const std::vector& plugins); + const std::vector& plugins); // When we start a new version of Chromium (different from our last run), we // need to discard the old crash stats so that we don't attribute crashes etc. @@ -423,7 +418,7 @@ class MetricsService : public NotificationObserver, std::string hardware_class_; // The list of plugins which was retrieved on the file thread. - std::vector plugins_; + std::vector plugins_; // The outstanding transmission appears as a URL Fetch operation. scoped_ptr current_fetch_; diff --git a/chrome/browser/mock_plugin_exceptions_table_model.cc b/chrome/browser/mock_plugin_exceptions_table_model.cc index 1c88524..77b2a2f 100644 --- a/chrome/browser/mock_plugin_exceptions_table_model.cc +++ b/chrome/browser/mock_plugin_exceptions_table_model.cc @@ -5,11 +5,11 @@ #include "chrome/browser/mock_plugin_exceptions_table_model.h" void MockPluginExceptionsTableModel::set_plugins( - std::vector& plugins) { + std::vector& plugins) { plugins_ = plugins; } void MockPluginExceptionsTableModel::GetPlugins( - std::vector* plugin_groups) { + std::vector* plugin_groups) { *plugin_groups = plugins_; } diff --git a/chrome/browser/mock_plugin_exceptions_table_model.h b/chrome/browser/mock_plugin_exceptions_table_model.h index c63d67f..15a1c5b 100644 --- a/chrome/browser/mock_plugin_exceptions_table_model.h +++ b/chrome/browser/mock_plugin_exceptions_table_model.h @@ -17,14 +17,13 @@ class MockPluginExceptionsTableModel : public PluginExceptionsTableModel { : PluginExceptionsTableModel(map, otr_map) {} virtual ~MockPluginExceptionsTableModel() {} - void set_plugins(std::vector& plugins); + void set_plugins(std::vector& plugins); protected: - virtual void GetPlugins( - std::vector* plugin_groups); + virtual void GetPlugins(std::vector* plugin_groups); private: - std::vector plugins_; + std::vector plugins_; }; #endif // CHROME_BROWSER_MOCK_PLUGIN_EXCEPTIONS_TABLE_MODEL_H_ diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc index 2b60d66..55e1405 100644 --- a/chrome/browser/plugin_carbon_interpose_mac.cc +++ b/chrome/browser/plugin_carbon_interpose_mac.cc @@ -8,7 +8,7 @@ #include "chrome/plugin/plugin_interpose_util_mac.h" #include "gfx/rect.h" -#include "webkit/plugins/npapi/carbon_plugin_window_tracker_mac.h" +#include "webkit/glue/plugins/carbon_plugin_window_tracker_mac.h" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -61,16 +61,16 @@ static void OnPluginWindowSelected(WindowRef window) { static Boolean ChromePluginIsWindowActive(WindowRef window) { const OpaquePluginRef delegate = - webkit::npapi::CarbonPluginWindowTracker::SharedInstance()-> - GetDelegateForDummyWindow(window); + CarbonPluginWindowTracker::SharedInstance()->GetDelegateForDummyWindow( + window); return delegate ? IsContainingWindowActive(delegate) : IsWindowActive(window); } static Boolean ChromePluginIsWindowHilited(WindowRef window) { const OpaquePluginRef delegate = - webkit::npapi::CarbonPluginWindowTracker::SharedInstance()-> - GetDelegateForDummyWindow(window); + CarbonPluginWindowTracker::SharedInstance()->GetDelegateForDummyWindow( + window); return delegate ? IsContainingWindowActive(delegate) : IsWindowHilited(window); } @@ -126,8 +126,8 @@ static void ChromePluginDisposeDialog(DialogRef dialog) { static WindowPartCode ChromePluginFindWindow(Point point, WindowRef* window) { OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate(); - webkit::npapi::CarbonPluginWindowTracker* tracker = - webkit::npapi::CarbonPluginWindowTracker::SharedInstance(); + CarbonPluginWindowTracker* tracker = + CarbonPluginWindowTracker::SharedInstance(); WindowRef plugin_window = tracker->GetDummyWindowForDelegate(delegate); if (plugin_window) { // If plugin_window is non-NULL, then we are in the middle of routing an diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc index fd7d9bd..74aa07c 100644 --- a/chrome/browser/plugin_data_remover.cc +++ b/chrome/browser/plugin_data_remover.cc @@ -10,8 +10,8 @@ #include "chrome/browser/browser_thread.h" #include "chrome/browser/plugin_service.h" #include "chrome/common/plugin_messages.h" -#include "webkit/plugins/npapi/plugin_group.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_group.h" +#include "webkit/glue/plugins/plugin_list.h" #if defined(OS_POSIX) #include "ipc/ipc_channel_posix.h" @@ -65,8 +65,7 @@ bool PluginDataRemover::OffTheRecord() { return false; } -void PluginDataRemover::SetPluginInfo( - const webkit::npapi::WebPluginInfo& info) { +void PluginDataRemover::SetPluginInfo(const WebPluginInfo& info) { } void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { @@ -143,16 +142,16 @@ void PluginDataRemover::SignalDone() { bool PluginDataRemover::IsSupported() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); bool allow_wildcard = false; - webkit::npapi::WebPluginInfo plugin; + WebPluginInfo plugin; std::string mime_type; - if (!webkit::npapi::PluginList::Singleton()->GetPluginInfo(GURL(), - g_flash_mime_type, - allow_wildcard, - &plugin, - &mime_type)) + if (!NPAPI::PluginList::Singleton()->GetPluginInfo(GURL(), + g_flash_mime_type, + allow_wildcard, + &plugin, + &mime_type)) return false; scoped_ptr version( - webkit::npapi::PluginGroup::CreateVersionFromString(plugin.version)); + PluginGroup::CreateVersionFromString(plugin.version)); scoped_ptr min_version( Version::GetVersionFromString(g_min_flash_version)); return plugin.enabled && diff --git a/chrome/browser/plugin_data_remover.h b/chrome/browser/plugin_data_remover.h index 58387fe..03b7e6f 100644 --- a/chrome/browser/plugin_data_remover.h +++ b/chrome/browser/plugin_data_remover.h @@ -41,7 +41,7 @@ class PluginDataRemover : public base::RefCountedThreadSafe, // PluginProcessHost::Client methods virtual int ID(); virtual bool OffTheRecord(); - virtual void SetPluginInfo(const webkit::npapi::WebPluginInfo& info); + virtual void SetPluginInfo(const WebPluginInfo& info); virtual void OnChannelOpened(const IPC::ChannelHandle& handle); virtual void OnError(); diff --git a/chrome/browser/plugin_exceptions_table_model.cc b/chrome/browser/plugin_exceptions_table_model.cc index 5b2a2c1..7ad5b13 100644 --- a/chrome/browser/plugin_exceptions_table_model.cc +++ b/chrome/browser/plugin_exceptions_table_model.cc @@ -134,13 +134,13 @@ void PluginExceptionsTableModel::ClearSettings() { } void PluginExceptionsTableModel::GetPlugins( - std::vector* plugin_groups) { - webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, plugin_groups); + std::vector* plugin_groups) { + NPAPI::PluginList::Singleton()->GetPluginGroups(false, plugin_groups); } void PluginExceptionsTableModel::LoadSettings() { int group_id = 0; - std::vector plugins; + std::vector plugins; GetPlugins(&plugins); for (size_t i = 0; i < plugins.size(); ++i) { std::string plugin = plugins[i].identifier(); diff --git a/chrome/browser/plugin_exceptions_table_model.h b/chrome/browser/plugin_exceptions_table_model.h index 045c218..d345b95 100644 --- a/chrome/browser/plugin_exceptions_table_model.h +++ b/chrome/browser/plugin_exceptions_table_model.h @@ -13,7 +13,7 @@ #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/remove_rows_table_model.h" #include "chrome/common/notification_observer.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" struct WebPluginInfo; @@ -48,8 +48,7 @@ class PluginExceptionsTableModel : public RemoveRowsTableModel, protected: // Subclasses can override this method for testing. - virtual void GetPlugins( - std::vector* plugin_groups); + virtual void GetPlugins(std::vector* plugin_groups); private: friend class PluginExceptionsTableModelTest; diff --git a/chrome/browser/plugin_exceptions_table_model_unittest.cc b/chrome/browser/plugin_exceptions_table_model_unittest.cc index e7efcca..b96f3fb 100644 --- a/chrome/browser/plugin_exceptions_table_model_unittest.cc +++ b/chrome/browser/plugin_exceptions_table_model_unittest.cc @@ -13,8 +13,8 @@ #include "chrome/test/testing_profile.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webkit/plugins/npapi/plugin_group.h" -#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/glue/plugins/plugin_group.h" +#include "webkit/glue/plugins/webplugininfo.h" // Can't be an internal namespace because PluginExceptionsTableModel declares // as a friend. @@ -85,21 +85,21 @@ class PluginExceptionsTableModelTest : public testing::Test { table_model_.reset(new MockPluginExceptionsTableModel(map, NULL)); - std::vector plugins; - webkit::npapi::WebPluginInfo foo_plugin; + std::vector plugins; + WebPluginInfo foo_plugin; foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo")); foo_plugin.name = ASCIIToUTF16("FooPlugin"); foo_plugin.enabled = true; - scoped_ptr foo_group( - webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin)); + scoped_ptr foo_group( + PluginGroup::FromWebPluginInfo(foo_plugin)); plugins.push_back(*foo_group); - webkit::npapi::WebPluginInfo bar_plugin; + WebPluginInfo bar_plugin; bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar")); bar_plugin.name = ASCIIToUTF16("BarPlugin"); bar_plugin.enabled = true; - scoped_ptr bar_group( - webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin)); + scoped_ptr bar_group( + PluginGroup::FromWebPluginInfo(bar_plugin)); plugins.push_back(*bar_group); table_model_->set_plugins(plugins); diff --git a/chrome/browser/plugin_installer.cc b/chrome/browser/plugin_installer.cc index 8d63679..b6ceb3c 100644 --- a/chrome/browser/plugin_installer.cc +++ b/chrome/browser/plugin_installer.cc @@ -12,7 +12,7 @@ #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" -#include "webkit/plugins/npapi/default_plugin_shared.h" +#include "webkit/glue/plugins/default_plugin_shared.h" // The URL for the "Problems installing" page for the Plugins infobar. static const char kLearnMorePluginInstallerUrl[] = @@ -30,11 +30,11 @@ PluginInstaller::~PluginInstaller() { void PluginInstaller::OnMissingPluginStatus(int status) { switch (status) { - case webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE: { + case default_plugin::MISSING_PLUGIN_AVAILABLE: { tab_contents_->AddInfoBar(this); break; } - case webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: { + case default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: { // Hide the InfoBar if user already started download/install of the // missing plugin. tab_contents_->RemoveInfoBar(this); diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 72d8aed..0e7735a 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -169,7 +169,7 @@ PluginProcessHost::~PluginProcessHost() { CancelRequests(); } -bool PluginProcessHost::Init(const webkit::npapi::WebPluginInfo& info, +bool PluginProcessHost::Init(const WebPluginInfo& info, const std::string& locale) { info_ = info; set_name(UTF16ToWideHack(info_.name)); diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index b98840e..89e368a 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -18,7 +18,7 @@ #include "chrome/browser/browser_child_process_host.h" #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "gfx/native_widget_types.h" -#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/glue/plugins/webplugininfo.h" namespace gfx { class Rect; @@ -47,7 +47,7 @@ class PluginProcessHost : public BrowserChildProcessHost, // the channel. virtual int ID() = 0; virtual bool OffTheRecord() = 0; - virtual void SetPluginInfo(const webkit::npapi::WebPluginInfo& info) = 0; + virtual void SetPluginInfo(const WebPluginInfo& info) = 0; // The client should delete itself when one of these methods is called. virtual void OnChannelOpened(const IPC::ChannelHandle& handle) = 0; virtual void OnError() = 0; @@ -61,7 +61,7 @@ class PluginProcessHost : public BrowserChildProcessHost, // Initialize the new plugin process, returning true on success. This must // be called before the object can be used. - bool Init(const webkit::npapi::WebPluginInfo& info, const std::string& locale); + bool Init(const WebPluginInfo& info, const std::string& locale); // Force the plugin process to shutdown (cleanly). virtual void ForceShutdown(); @@ -92,7 +92,7 @@ class PluginProcessHost : public BrowserChildProcessHost, void OnAppActivation(); #endif - const webkit::npapi::WebPluginInfo& info() const { return info_; } + const WebPluginInfo& info() const { return info_; } #if defined(OS_WIN) // Tracks plugin parent windows created on the browser UI thread. @@ -150,7 +150,7 @@ class PluginProcessHost : public BrowserChildProcessHost, std::queue sent_requests_; // Information about the plugin. - webkit::npapi::WebPluginInfo info_; + WebPluginInfo info_; // Helper class for handling PluginProcessHost_ResolveProxy messages (manages // the requests to the proxy service). diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 50677f7..548bd3c 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -34,13 +34,12 @@ #include "chrome/common/plugin_messages.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" -#include "webkit/plugins/npapi/plugin_constants_win.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugininfo.h" - #ifndef DISABLE_NACL #include "native_client/src/trusted/plugin/nacl_entry_points.h" #endif +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugininfo.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/plugin_selection_policy.h" @@ -95,10 +94,10 @@ PluginService::PluginService() const CommandLine* command_line = CommandLine::ForCurrentProcess(); FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin); if (!path.empty()) - webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); + NPAPI::PluginList::Singleton()->AddExtraPluginPath(path); path = command_line->GetSwitchValuePath(switches::kExtraPluginDir); if (!path.empty()) - webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path); + NPAPI::PluginList::Singleton()->AddExtraPluginDir(path); chrome::RegisterInternalDefaultPlugin(); @@ -106,7 +105,7 @@ PluginService::PluginService() if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableInternalFlash) && PathService::Get(chrome::FILE_FLASH_PLUGIN, &path)) { - webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); + NPAPI::PluginList::Singleton()->AddExtraPluginPath(path); } #ifndef DISABLE_NACL @@ -124,9 +123,9 @@ PluginService::PluginService() #if defined(OS_WIN) hkcu_key_.Create( - HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); + HKEY_CURRENT_USER, kRegistryMozillaPlugins, KEY_NOTIFY); hklm_key_.Create( - HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); + HKEY_LOCAL_MACHINE, kRegistryMozillaPlugins, KEY_NOTIFY); if (hkcu_key_.StartWatching()) { hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); hkcu_watcher_.StartWatching(hkcu_event_.get(), this); @@ -141,7 +140,7 @@ PluginService::PluginService() // e.g. ~/.config/chromium/Plugins. FilePath user_data_dir; if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { - webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( + NPAPI::PluginList::Singleton()->AddExtraPluginDir( user_data_dir.Append("Plugins")); } #endif @@ -213,9 +212,9 @@ PluginProcessHost* PluginService::FindOrStartPluginProcess( if (plugin_host) return plugin_host; - webkit::npapi::WebPluginInfo info; - if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( - plugin_path, &info)) { + WebPluginInfo info; + if (!NPAPI::PluginList::Singleton()->GetPluginInfoByPath( + plugin_path, &info)) { return NULL; } @@ -247,7 +246,7 @@ void PluginService::GetAllowedPluginForOpenChannelToPlugin( const std::string& mime_type, PluginProcessHost::Client* client) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - webkit::npapi::WebPluginInfo info; + WebPluginInfo info; bool found = GetFirstAllowedPluginInfo(url, mime_type, &info, NULL); FilePath plugin_path; if (found && info.enabled) @@ -276,16 +275,16 @@ void PluginService::FinishOpenChannelToPlugin( bool PluginService::GetFirstAllowedPluginInfo( const GURL& url, const std::string& mime_type, - webkit::npapi::WebPluginInfo* info, + WebPluginInfo* info, std::string* actual_mime_type) { // GetPluginInfoArray may need to load the plugins, so we need to be // on the FILE thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); bool allow_wildcard = true; #if defined(OS_CHROMEOS) - std::vector info_array; + std::vector info_array; std::vector actual_mime_types; - webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( + NPAPI::PluginList::Singleton()->GetPluginInfoArray( url, mime_type, allow_wildcard, &info_array, &actual_mime_types); // Now we filter by the plugin selection policy. @@ -299,7 +298,7 @@ bool PluginService::GetFirstAllowedPluginInfo( } return false; #else - return webkit::npapi::PluginList::Singleton()->GetPluginInfo( + return NPAPI::PluginList::Singleton()->GetPluginInfo( url, mime_type, allow_wildcard, info, actual_mime_type); #endif } @@ -320,7 +319,7 @@ void PluginService::OnWaitableEventSignaled( hklm_key_.StartWatching(); } - webkit::npapi::PluginList::Singleton()->RefreshPlugins(); + NPAPI::PluginList::Singleton()->RefreshPlugins(); PurgePluginListCache(true); #endif // defined(OS_WIN) } @@ -341,8 +340,8 @@ void PluginService::Observe(NotificationType type, bool plugins_changed = false; for (size_t i = 0; i < extension->plugins().size(); ++i) { const Extension::PluginInfo& plugin = extension->plugins()[i]; - webkit::npapi::PluginList::Singleton()->RefreshPlugins(); - webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path); + NPAPI::PluginList::Singleton()->RefreshPlugins(); + NPAPI::PluginList::Singleton()->AddExtraPluginPath(plugin.path); plugins_changed = true; if (!plugin.is_public) private_plugins_[plugin.path] = extension->url(); @@ -360,9 +359,8 @@ void PluginService::Observe(NotificationType type, BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableFunction(&ForceShutdownPlugin, plugin.path)); - webkit::npapi::PluginList::Singleton()->RefreshPlugins(); - webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath( - plugin.path); + NPAPI::PluginList::Singleton()->RefreshPlugins(); + NPAPI::PluginList::Singleton()->RemoveExtraPluginPath(plugin.path); plugins_changed = true; if (!plugin.is_public) private_plugins_.erase(plugin.path); @@ -409,7 +407,7 @@ void PluginService::RegisterPepperPlugins() { std::vector plugins; PepperPluginRegistry::GetList(&plugins); for (size_t i = 0; i < plugins.size(); ++i) { - webkit::npapi::PluginVersionInfo info; + NPAPI::PluginVersionInfo info; info.path = plugins[i].path; info.product_name = plugins[i].name.empty() ? plugins[i].path.BaseName().ToWStringHack() : @@ -424,6 +422,6 @@ void PluginService::RegisterPepperPlugins() { // or perhaps refactor the PluginList to be less specific to NPAPI. memset(&info.entry_points, 0, sizeof(info.entry_points)); - webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); + NPAPI::PluginList::Singleton()->RegisterInternalPlugin(info); } } diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h index a66d76ac..e83e804 100644 --- a/chrome/browser/plugin_service.h +++ b/chrome/browser/plugin_service.h @@ -41,13 +41,7 @@ class MessageLoop; class Profile; class ResourceDispatcherHost; class URLRequestContext; - - -namespace webkit { -namespace npapi { struct WebPluginInfo; -} -} // This must be created on the main thread but it's only called on the IO/file // thread. @@ -96,7 +90,7 @@ class PluginService // the given url and mime type. Must be called on the FILE thread. bool GetFirstAllowedPluginInfo(const GURL& url, const std::string& mime_type, - webkit::npapi::WebPluginInfo* info, + WebPluginInfo* info, std::string* actual_mime_type); // Returns true if the given plugin is allowed to be used by a page with diff --git a/chrome/browser/plugin_service_browsertest.cc b/chrome/browser/plugin_service_browsertest.cc index 5fed897..8d9e82e 100644 --- a/chrome/browser/plugin_service_browsertest.cc +++ b/chrome/browser/plugin_service_browsertest.cc @@ -11,7 +11,7 @@ #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gmock/include/gmock/gmock.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { @@ -26,7 +26,7 @@ class MockPluginProcessHostClient : public PluginProcessHost::Client { MOCK_METHOD0(ID, int()); MOCK_METHOD0(OffTheRecord, bool()); - MOCK_METHOD1(SetPluginInfo, void(const webkit::npapi::WebPluginInfo& info)); + MOCK_METHOD1(SetPluginInfo, void(const WebPluginInfo& info)); MOCK_METHOD1(OnChannelOpened, void(const IPC::ChannelHandle& handle)); MOCK_METHOD0(OnError, void()); @@ -73,10 +73,10 @@ IN_PROC_BROWSER_TEST_F(PluginServiceTest, StartAndFindPluginProcess) { // calls to FindPluginProcess should return non-zero values. PluginProcessHost* default_plugin_process_host = plugin_service_->FindOrStartPluginProcess( - FilePath(webkit::npapi::kDefaultPluginLibraryName)); + FilePath(kDefaultPluginLibraryName)); - EXPECT_EQ(default_plugin_process_host, plugin_service_->FindPluginProcess( - FilePath(webkit::npapi::kDefaultPluginLibraryName))); + EXPECT_EQ(default_plugin_process_host, + plugin_service_->FindPluginProcess(FilePath(kDefaultPluginLibraryName))); } IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) { @@ -95,7 +95,7 @@ IN_PROC_BROWSER_TEST_F(PluginServiceTest, GetFirstAllowedPluginInfo) { // We should always get a positive response no matter whether we really have // a plugin to support that particular mime type because the Default plugin // supports all mime types. - webkit::npapi::WebPluginInfo plugin_info; + WebPluginInfo plugin_info; std::string plugin_mime_type; plugin_service_->GetFirstAllowedPluginInfo(GURL("http://google.com/"), "application/pdf", diff --git a/chrome/browser/plugin_service_unittest.cc b/chrome/browser/plugin_service_unittest.cc index 6950d2a..4e54526 100644 --- a/chrome/browser/plugin_service_unittest.cc +++ b/chrome/browser/plugin_service_unittest.cc @@ -9,6 +9,7 @@ #include "chrome/browser/browser_thread.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { diff --git a/chrome/browser/plugin_updater.cc b/chrome/browser/plugin_updater.cc index d994efd..40f3be1 100644 --- a/chrome/browser/plugin_updater.cc +++ b/chrome/browser/plugin_updater.cc @@ -22,8 +22,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/pref_names.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/glue/plugins/webplugininfo.h" // How long to wait to save the plugin enabled information, which might need to // go to disk. @@ -35,7 +34,7 @@ PluginUpdater::PluginUpdater() } DictionaryValue* PluginUpdater::CreatePluginFileSummary( - const webkit::npapi::WebPluginInfo& plugin) { + const WebPluginInfo& plugin) { DictionaryValue* data = new DictionaryValue(); data->SetString("path", plugin.path.value()); data->SetString("name", plugin.name); @@ -46,8 +45,8 @@ DictionaryValue* PluginUpdater::CreatePluginFileSummary( // static ListValue* PluginUpdater::GetPluginGroupsData() { - std::vector plugin_groups; - webkit::npapi::PluginList::Singleton()->GetPluginGroups(true, &plugin_groups); + std::vector plugin_groups; + NPAPI::PluginList::Singleton()->GetPluginGroups(true, &plugin_groups); // Construct DictionaryValues to return to the UI ListValue* plugin_groups_data = new ListValue(); @@ -58,20 +57,19 @@ ListValue* PluginUpdater::GetPluginGroupsData() { } void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) { - if (webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy(group_name)) + if (PluginGroup::IsPluginNameDisabledByPolicy(group_name)) enable = false; - webkit::npapi::PluginList::Singleton()->EnableGroup(enable, group_name); + NPAPI::PluginList::Singleton()->EnableGroup(enable, group_name); NotifyPluginStatusChanged(); } void PluginUpdater::EnablePluginFile(bool enable, const FilePath::StringType& path) { FilePath file_path(path); - if (enable && - !webkit::npapi::PluginGroup::IsPluginPathDisabledByPolicy(file_path)) - webkit::npapi::PluginList::Singleton()->EnablePlugin(file_path); + if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path)) + NPAPI::PluginList::Singleton()->EnablePlugin(file_path); else - webkit::npapi::PluginList::Singleton()->DisablePlugin(file_path); + NPAPI::PluginList::Singleton()->DisablePlugin(file_path); NotifyPluginStatusChanged(); } @@ -107,8 +105,7 @@ void PluginUpdater::DisablePluginsFromPolicy(const ListValue* plugin_names) { } } } - webkit::npapi::PluginGroup::SetPolicyDisabledPluginPatterns( - policy_disabled_plugin_patterns); + PluginGroup::SetPolicyDisabledPluginPatterns(policy_disabled_plugin_patterns); NotifyPluginStatusChanged(); } @@ -193,7 +190,7 @@ void PluginUpdater::DisablePluginGroupsFromPrefs(Profile* profile) { } } if (!enabled) - webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_path); + NPAPI::PluginList::Singleton()->DisablePlugin(plugin_path); } else if (!enabled && plugin->GetString("name", &group_name)) { // Don't disable this group if it's for the pdf plugin and we just // forced it on. @@ -216,14 +213,13 @@ void PluginUpdater::DisablePluginGroupsFromPrefs(Profile* profile) { !force_internal_pdf_for_this_run) { // The internal PDF plugin is disabled by default, and the user hasn't // overridden the default. - webkit::npapi::PluginList::Singleton()->DisablePlugin(pdf_path); + NPAPI::PluginList::Singleton()->DisablePlugin(pdf_path); EnablePluginGroup(false, pdf_group_name); } if (force_enable_internal_pdf) { // See http://crbug.com/50105 for background. - EnablePluginGroup(false, ASCIIToUTF16( - webkit::npapi::PluginGroup::kAdobeReaderGroupName)); + EnablePluginGroup(false, ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName)); // We want to save this, but doing so requires loading the list of plugins, // so do it after a minute as to not impact startup performance. Note that @@ -241,11 +237,11 @@ void PluginUpdater::UpdatePreferences(Profile* profile, int delay_ms) { } void PluginUpdater::GetPreferencesDataOnFileThread(void* profile) { - std::vector plugins; - webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins); + std::vector plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); - std::vector groups; - webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups); + std::vector groups; + NPAPI::PluginList::Singleton()->GetPluginGroups(false, &groups); BrowserThread::PostTask( BrowserThread::UI, @@ -257,8 +253,8 @@ void PluginUpdater::GetPreferencesDataOnFileThread(void* profile) { void PluginUpdater::OnUpdatePreferences( Profile* profile, - const std::vector& plugins, - const std::vector& groups) { + const std::vector& plugins, + const std::vector& groups) { ListValue* plugins_list = profile->GetPrefs()->GetMutableList( prefs::kPluginsPluginsList); plugins_list->Clear(); @@ -269,8 +265,7 @@ void PluginUpdater::OnUpdatePreferences( internal_dir); // Add the plugin files. - for (std::vector::const_iterator it = - plugins.begin(); + for (std::vector::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { plugins_list->Append(CreatePluginFileSummary(*it)); diff --git a/chrome/browser/plugin_updater.h b/chrome/browser/plugin_updater.h index dc18595..5264334 100644 --- a/chrome/browser/plugin_updater.h +++ b/chrome/browser/plugin_updater.h @@ -12,19 +12,15 @@ #include "base/file_path.h" #include "base/singleton.h" #include "chrome/common/notification_observer.h" +#include "webkit/glue/plugins/plugin_list.h" class DictionaryValue; class ListValue; class NotificationDetails; class NotificationSource; -class Profile; - -namespace webkit { -namespace npapi { class PluginGroup; +class Profile; struct WebPluginInfo; -} -} class PluginUpdater : public NotificationObserver { public: @@ -62,8 +58,8 @@ class PluginUpdater : public NotificationObserver { // Called on the UI thread with the plugin data to save the preferences. static void OnUpdatePreferences( Profile* profile, - const std::vector& plugins, - const std::vector& groups); + const std::vector& plugins, + const std::vector& groups); // Queues sending the notification that plugin data has changed. This is done // so that if a bunch of changes happen, we only send one notification. @@ -72,8 +68,7 @@ class PluginUpdater : public NotificationObserver { // Used for the post task to notify that plugin enabled status changed. static void OnNotifyPluginStatusChanged(); - static DictionaryValue* CreatePluginFileSummary( - const webkit::npapi::WebPluginInfo& plugin); + static DictionaryValue* CreatePluginFileSummary(const WebPluginInfo& plugin); // Force plugins to be disabled due to policy. |plugins| contains // the list of StringValues of the names of the policy-disabled plugins. diff --git a/chrome/browser/renderer_host/accelerated_surface_container_mac.cc b/chrome/browser/renderer_host/accelerated_surface_container_mac.cc index f379931..1a7c07c 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_mac.cc +++ b/chrome/browser/renderer_host/accelerated_surface_container_mac.cc @@ -7,7 +7,7 @@ #include "app/surface/io_surface_support_mac.h" #include "base/logging.h" #include "chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" AcceleratedSurfaceContainerMac::AcceleratedSurfaceContainerMac( AcceleratedSurfaceContainerManagerMac* manager, @@ -51,7 +51,7 @@ void AcceleratedSurfaceContainerMac::SetSizeAndTransportDIB( } void AcceleratedSurfaceContainerMac::SetGeometry( - const webkit::npapi::WebPluginGeometry& geom) { + const webkit_glue::WebPluginGeometry& geom) { visible_ = geom.visible; if (geom.rects_valid) clip_rect_ = geom.clip_rect; diff --git a/chrome/browser/renderer_host/accelerated_surface_container_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_mac.h index 45979e0..deda9ef 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_mac.h +++ b/chrome/browser/renderer_host/accelerated_surface_container_mac.h @@ -36,11 +36,9 @@ #include "gfx/native_widget_types.h" #include "gfx/rect.h" -namespace webkit { -namespace npapi { +namespace webkit_glue { struct WebPluginGeometry; } -} class AcceleratedSurfaceContainerManagerMac; @@ -67,7 +65,7 @@ class AcceleratedSurfaceContainerMac { // currently only pays attention to the clip width and height, since the // view in which it is hosted is responsible for positioning it on the // page.) - void SetGeometry(const webkit::npapi::WebPluginGeometry& geom); + void SetGeometry(const webkit_glue::WebPluginGeometry& geom); // Draws this accelerated surface's contents, texture mapped onto a quad in // the given OpenGL context. TODO(kbr): figure out and define exactly how the diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc index a96782b..1ad09ba 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc +++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/renderer_host/accelerated_surface_container_mac.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" AcceleratedSurfaceContainerManagerMac::AcceleratedSurfaceContainerManagerMac() : current_id_(0), @@ -86,7 +86,7 @@ void AcceleratedSurfaceContainerManagerMac::SetSizeAndTransportDIB( } void AcceleratedSurfaceContainerManagerMac::SetPluginContainerGeometry( - const webkit::npapi::WebPluginGeometry& move) { + const webkit_glue::WebPluginGeometry& move) { AutoLock lock(lock_); AcceleratedSurfaceContainerMac* container = MapIDToContainer(move.window); diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h index a2855a4..a03a5c4 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h +++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h @@ -14,11 +14,9 @@ #include "base/lock.h" #include "gfx/native_widget_types.h" -namespace webkit { -namespace npapi { +namespace webkit_glue { struct WebPluginGeometry; } -} class AcceleratedSurfaceContainerMac; @@ -65,8 +63,7 @@ class AcceleratedSurfaceContainerManagerMac { // Takes an update from WebKit about a plugin's position and size and moves // the plugin accordingly. - void SetPluginContainerGeometry( - const webkit::npapi::WebPluginGeometry& move); + void SetPluginContainerGeometry(const webkit_glue::WebPluginGeometry& move); // Draws the plugin container associated with the given id into the given // OpenGL context, which must already be current. diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc index bc35c42..82ca861 100644 --- a/chrome/browser/renderer_host/buffered_resource_handler.cc +++ b/chrome/browser/renderer_host/buffered_resource_handler.cc @@ -22,7 +22,7 @@ #include "net/base/mime_util.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace { @@ -422,18 +422,18 @@ bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { return false; if (need_plugin_list) { - if (!webkit::npapi::PluginList::Singleton()->PluginsLoaded()) { + if (!NPAPI::PluginList::Singleton()->PluginsLoaded()) { *need_plugin_list = true; return true; } } else { - DCHECK(webkit::npapi::PluginList::Singleton()->PluginsLoaded()); + DCHECK(NPAPI::PluginList::Singleton()->PluginsLoaded()); } // Finally, check the plugin list. - webkit::npapi::WebPluginInfo info; + WebPluginInfo info; bool allow_wildcard = false; - return !webkit::npapi::PluginList::Singleton()->GetPluginInfo( + return !NPAPI::PluginList::Singleton()->GetPluginInfo( GURL(), type, allow_wildcard, &info, NULL) || !info.enabled; } @@ -469,8 +469,8 @@ void BufferedResourceHandler::UseAlternateResourceHandler( } void BufferedResourceHandler::LoadPlugins() { - std::vector plugins; - webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins); + std::vector plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc index 453e5c5..ad49440 100644 --- a/chrome/browser/renderer_host/render_message_filter.cc +++ b/chrome/browser/renderer_host/render_message_filter.cc @@ -65,11 +65,11 @@ #include "net/url_request/url_request_context.h" #include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h" #include "webkit/glue/context_menu.h" +#include "webkit/glue/plugins/plugin_group.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webcookie.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/plugin_group.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugin.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/plugin_selection_policy.h" @@ -200,7 +200,7 @@ class OpenChannelToPluginCallback : public PluginProcessHost::Client { return filter_->off_the_record(); } - virtual void SetPluginInfo(const webkit::npapi::WebPluginInfo& info) { + virtual void SetPluginInfo(const WebPluginInfo& info) { info_ = info; } @@ -223,7 +223,7 @@ class OpenChannelToPluginCallback : public PluginProcessHost::Client { scoped_refptr filter_; IPC::Message* reply_msg_; - webkit::npapi::WebPluginInfo info_; + WebPluginInfo info_; }; } // namespace @@ -684,8 +684,8 @@ void RenderMessageFilter::OnGetPlugins(bool refresh, void RenderMessageFilter::OnGetPluginsOnFileThread( bool refresh, IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - std::vector plugins; - webkit::npapi::PluginList::Singleton()->GetEnabledPlugins(refresh, &plugins); + std::vector plugins; + NPAPI::PluginList::Singleton()->GetEnabledPlugins(refresh, &plugins); ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -711,7 +711,7 @@ void RenderMessageFilter::OnGetPluginInfoOnFileThread( const std::string& mime_type, IPC::Message* reply_msg) { std::string actual_mime_type; - webkit::npapi::WebPluginInfo info; + WebPluginInfo info; bool found = plugin_service_->GetFirstAllowedPluginInfo(url, mime_type, &info, @@ -723,20 +723,18 @@ void RenderMessageFilter::OnGetPluginInfoOnFileThread( found, info, actual_mime_type, policy_url, reply_msg)); } -void RenderMessageFilter::OnGotPluginInfo( - bool found, - const webkit::npapi::WebPluginInfo& info, - const std::string& actual_mime_type, - const GURL& policy_url, - IPC::Message* reply_msg) { +void RenderMessageFilter::OnGotPluginInfo(bool found, + const WebPluginInfo& info, + const std::string& actual_mime_type, + const GURL& policy_url, + IPC::Message* reply_msg) { ContentSetting setting = CONTENT_SETTING_DEFAULT; - webkit::npapi::WebPluginInfo info_copy = info; + WebPluginInfo info_copy = info; if (found) { info_copy.enabled = info_copy.enabled && plugin_service_->PrivatePluginAllowedForURL(info_copy.path, policy_url); std::string resource = - webkit::npapi::PluginList::Singleton()->GetPluginGroupIdentifier( - info_copy); + NPAPI::PluginList::Singleton()->GetPluginGroupIdentifier(info_copy); setting = content_settings_->GetContentSetting( policy_url, CONTENT_SETTINGS_TYPE_PLUGINS, diff --git a/chrome/browser/renderer_host/render_message_filter.h b/chrome/browser/renderer_host/render_message_filter.h index 5c988b8..9a8a745 100644 --- a/chrome/browser/renderer_host/render_message_filter.h +++ b/chrome/browser/renderer_host/render_message_filter.h @@ -41,12 +41,7 @@ class RenderWidgetHelper; class URLRequestContextGetter; struct ViewHostMsg_CreateWindow_Params; struct ViewHostMsg_CreateWorker_Params; - -namespace webkit { -namespace npapi { struct WebPluginInfo; -} -} namespace base { class SharedMemory; @@ -158,7 +153,7 @@ class RenderMessageFilter : public BrowserMessageFilter, const std::string& mime_type, IPC::Message* reply_msg); void OnGotPluginInfo(bool found, - const webkit::npapi::WebPluginInfo& info, + const WebPluginInfo& info, const std::string& actual_mime_type, const GURL& policy_url, IPC::Message* reply_msg); diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index b4bb0e2..3c71440b 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -22,8 +22,8 @@ #include "chrome/common/render_messages.h" #include "chrome/common/render_messages_params.h" #include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webcursor.h" -#include "webkit/plugins/npapi/webplugin.h" #if defined(TOOLKIT_VIEWS) #include "views/view.h" diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 2d4b1ea..fdbe440 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -39,13 +39,8 @@ struct ViewHostMsg_AccessibilityNotification_Params; namespace webkit_glue { struct WebAccessibility; -} - -namespace webkit { -namespace npapi { struct WebPluginGeometry; } -} // RenderWidgetHostView is an interface implemented by an object that acts as // the "View" portion of a RenderWidgetHost. The RenderWidgetHost and its @@ -102,7 +97,7 @@ class RenderWidgetHostView { // Moves all plugin windows as described in the given list. virtual void MovePluginWindows( - const std::vector& moves) = 0; + const std::vector& moves) = 0; // Actually set/take focus to/from the associated View component. virtual void Focus() = 0; diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index b091890ef..e90e096 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -38,9 +38,9 @@ #include "chrome/common/native_web_keyboard_event.h" #include "gfx/gtk_preserve_window.h" #include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webcursor_gtk_data.h" -#include "webkit/plugins/npapi/webplugin.h" #if defined(OS_CHROMEOS) #include "views/widget/tooltip_window_gtk.h" @@ -587,7 +587,7 @@ gfx::NativeView RenderWidgetHostViewGtk::GetNativeView() { } void RenderWidgetHostViewGtk::MovePluginWindows( - const std::vector& moves) { + const std::vector& moves) { for (size_t i = 0; i < moves.size(); ++i) { plugin_container_manager_.MovePluginContainer(moves[i]); } diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h index 2c47c01..9f9b2e2 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -19,8 +19,8 @@ #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "gfx/native_widget_types.h" #include "gfx/rect.h" +#include "webkit/glue/plugins/gtk_plugin_container_manager.h" #include "webkit/glue/webcursor.h" -#include "webkit/plugins/npapi/gtk_plugin_container_manager.h" class RenderWidgetHost; class GtkIMContextWrapper; @@ -61,7 +61,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, virtual void SetSize(const gfx::Size& size); virtual gfx::NativeView GetNativeView(); virtual void MovePluginWindows( - const std::vector& moves); + const std::vector& moves); virtual void Focus(); virtual void Blur(); virtual bool HasFocus(); @@ -208,7 +208,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, scoped_ptr key_bindings_handler_; // Helper class that lets us allocate plugin containers and move them. - webkit::npapi::GtkPluginContainerManager plugin_container_manager_; + GtkPluginContainerManager plugin_container_manager_; // The size that we want the renderer to be. We keep this in a separate // variable because resizing in GTK+ is async. diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index d538758..46efeee 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -184,7 +184,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual void SetSize(const gfx::Size& size); virtual gfx::NativeView GetNativeView(); virtual void MovePluginWindows( - const std::vector& moves); + const std::vector& moves); virtual void Focus(); virtual void Blur(); virtual bool HasFocus(); diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index 60cc85e..22175dc 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -40,8 +40,8 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webaccessibility.h" -#include "webkit/plugins/npapi/webplugin.h" #import "third_party/mozilla/ComplexTextInputPanel.h" using WebKit::WebInputEvent; @@ -623,15 +623,15 @@ gfx::NativeView RenderWidgetHostViewMac::GetNativeView() { } void RenderWidgetHostViewMac::MovePluginWindows( - const std::vector& moves) { + const std::vector& moves) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // Handle movement of accelerated plugins, which are the only "windowed" // plugins that exist on the Mac. - for (std::vector::const_iterator iter = + for (std::vector::const_iterator iter = moves.begin(); iter != moves.end(); ++iter) { - webkit::npapi::WebPluginGeometry geom = *iter; + webkit_glue::WebPluginGeometry geom = *iter; AcceleratedPluginView* view = ViewForPluginWindowHandle(geom.window); DCHECK(view); @@ -978,14 +978,14 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( // Fake up a WebPluginGeometry for the root window to set the // container's size; we will never get a notification from the // browser about the root window, only plugins. - webkit::npapi::WebPluginGeometry geom; + webkit_glue::WebPluginGeometry geom; gfx::Rect rect(0, 0, width, height); geom.window = window; geom.window_rect = rect; geom.clip_rect = rect; geom.visible = true; geom.rects_valid = true; - MovePluginWindows(std::vector(1, geom)); + MovePluginWindows(std::vector(1, geom)); } } diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm index a36c88f..521e48d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -57,7 +57,7 @@ class RenderWidgetHostViewMacTest : public RenderViewHostTestHarness { // The accelerated view isn't shown until it has a valid rect and has been // painted to. rwhv_mac_->AcceleratedSurfaceBuffersSwapped(accelerated_handle, 0, 0, 0, 0); - webkit::npapi::WebPluginGeometry geom; + webkit_glue::WebPluginGeometry geom; gfx::Rect rect(0, 0, w, h); geom.window = accelerated_handle; geom.window_rect = rect; @@ -65,7 +65,7 @@ class RenderWidgetHostViewMacTest : public RenderViewHostTestHarness { geom.visible = true; geom.rects_valid = true; rwhv_mac_->MovePluginWindows( - std::vector(1, geom)); + std::vector(1, geom)); return accelerated_handle; } diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc index c48a1a9..cb17689 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc @@ -193,7 +193,7 @@ void RenderWidgetHostViewViews::SetSize(const gfx::Size& size) { } void RenderWidgetHostViewViews::MovePluginWindows( - const std::vector& moves) { + const std::vector& moves) { // TODO(anicolao): NIY // NOTIMPLEMENTED(); } diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.h b/chrome/browser/renderer_host/render_widget_host_view_views.h index 8a582a7..9c5c8cb 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.h +++ b/chrome/browser/renderer_host/render_widget_host_view_views.h @@ -44,7 +44,7 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView, virtual void WasHidden(); virtual void SetSize(const gfx::Size& size); virtual void MovePluginWindows( - const std::vector& moves); + const std::vector& moves); virtual void Focus(); virtual void Blur(); virtual bool HasFocus(); diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 6a86bc0..f5afe70 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -46,11 +46,11 @@ #include "views/focus/focus_util_win.h" // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h! #include "views/widget/widget_win.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webcursor.h" -#include "webkit/plugins/npapi/plugin_constants_win.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" -#include "webkit/plugins/npapi/webplugin.h" using app::ViewProp; using base::TimeDelta; @@ -59,7 +59,7 @@ using WebKit::WebInputEvent; using WebKit::WebInputEventFactory; using WebKit::WebMouseEvent; using WebKit::WebTextDirection; -using webkit::npapi::WebPluginGeometry; +using webkit_glue::WebPluginGeometry; const wchar_t kRenderWidgetHostHWNDClass[] = L"Chrome_RenderWidgetHostHWND"; @@ -236,7 +236,7 @@ class NotifyPluginProcessHostTask : public Task { // Windows callback for OnDestroy to detach the plugin windows. BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { - if (webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(window) && + if (WebPluginDelegateImpl::IsPluginDelegateWindow(window) && !IsHungAppWindow(window)) { ::ShowWindow(window, SW_HIDE); SetParent(window, NULL); @@ -490,7 +490,7 @@ HWND RenderWidgetHostViewWin::ReparentWindow(HWND window) { wcex.hCursor = 0; wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW+1); wcex.lpszMenuName = 0; - wcex.lpszClassName = webkit::npapi::kWrapperNativeWindowClassName; + wcex.lpszClassName = kWrapperNativeWindowClassName; wcex.hIconSm = 0; window_class = RegisterClassEx(&wcex); } @@ -654,11 +654,11 @@ void RenderWidgetHostViewWin::ImeCancelComposition() { } BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) { - if (!webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd)) + if (!WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd)) return TRUE; gfx::Rect* rect = reinterpret_cast(lparam); - static UINT msg = RegisterWindowMessage(webkit::npapi::kPaintMessageName); + static UINT msg = RegisterWindowMessage(kPaintMessageName); WPARAM wparam = rect->x() << 16 | rect->y(); lparam = rect->width() << 16 | rect->height(); @@ -1447,8 +1447,7 @@ LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message, ::ScreenToClient(m_hWnd, &cursor_pos); HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos); if (::IsWindow(child_window) && child_window != m_hWnd) { - if (win_util::GetClassName(child_window) == - webkit::npapi::kWrapperNativeWindowClassName) + if (win_util::GetClassName(child_window) == kWrapperNativeWindowClassName) child_window = ::GetWindow(child_window, GW_CHILD); ::SetFocus(child_window); diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index 50e59a6..1f67814 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -132,7 +132,7 @@ class RenderWidgetHostViewWin virtual void SetSize(const gfx::Size& size); virtual gfx::NativeView GetNativeView(); virtual void MovePluginWindows( - const std::vector& moves); + const std::vector& moves); virtual void Focus(); virtual void Blur(); virtual bool HasFocus(); diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h index f84bc21..7aa9638 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -60,7 +60,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual void SetSize(const gfx::Size& size) {} virtual gfx::NativeView GetNativeView() { return NULL; } virtual void MovePluginWindows( - const std::vector& moves) {} + const std::vector& moves) {} #if defined(OS_WIN) virtual void ForwardMouseEventToRenderer(UINT message, WPARAM wparam, diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 8f5ed48..46498e3 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -113,7 +113,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "webkit/glue/webpreferences.h" #include "webkit/glue/password_form.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" // Cross-Site Navigations // @@ -2091,8 +2091,8 @@ void TabContents::OnCrashedPlugin(const FilePath& plugin_path) { DCHECK(!plugin_path.value().empty()); std::wstring plugin_name = plugin_path.ToWStringHack(); - webkit::npapi::WebPluginInfo plugin_info; - if (webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( + WebPluginInfo plugin_info; + if (NPAPI::PluginList::Singleton()->GetPluginInfoByPath( plugin_path, &plugin_info) && !plugin_info.name.empty()) { plugin_name = UTF16ToWide(plugin_info.name); diff --git a/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm b/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm index 746d8a1..051d58b 100644 --- a/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/table_model_array_controller_unittest.mm @@ -15,8 +15,8 @@ #include "grit/generated_resources.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugininfo.h" class TableModelArrayControllerTest : public CocoaTest { public: @@ -50,27 +50,27 @@ class TableModelArrayControllerTest : public CocoaTest { model_.reset(new MockPluginExceptionsTableModel(map, NULL)); - std::vector plugins; - webkit::npapi::WebPluginInfo foo_plugin; + std::vector plugins; + WebPluginInfo foo_plugin; foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo")); foo_plugin.name = ASCIIToUTF16("FooPlugin"); foo_plugin.enabled = true; - scoped_ptr foo_group( - webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin)); + scoped_ptr foo_group( + PluginGroup::FromWebPluginInfo(foo_plugin)); plugins.push_back(*foo_group); - webkit::npapi::WebPluginInfo bar_plugin; + WebPluginInfo bar_plugin; bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar")); bar_plugin.name = ASCIIToUTF16("BarPlugin"); bar_plugin.enabled = true; - scoped_ptr bar_group( - webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin)); + scoped_ptr bar_group( + PluginGroup::FromWebPluginInfo(bar_plugin)); plugins.push_back(*bar_group); - webkit::npapi::WebPluginInfo blurp_plugin; + WebPluginInfo blurp_plugin; blurp_plugin.path = FilePath(FILE_PATH_LITERAL("c-blurp")); blurp_plugin.name = ASCIIToUTF16("BlurpPlugin"); blurp_plugin.enabled = true; - scoped_ptr blurp_group( - webkit::npapi::PluginGroup::FromWebPluginInfo(blurp_plugin)); + scoped_ptr blurp_group( + PluginGroup::FromWebPluginInfo(blurp_plugin)); plugins.push_back(*blurp_group); model_->set_plugins(plugins); diff --git a/chrome/common/chrome_plugin_lib.cc b/chrome/common/chrome_plugin_lib.cc index 1bd118b..3277f4a 100644 --- a/chrome/common/chrome_plugin_lib.cc +++ b/chrome/common/chrome_plugin_lib.cc @@ -19,7 +19,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/chrome_paths.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" using base::TimeDelta; @@ -114,7 +114,7 @@ void ChromePluginLib::RegisterPluginsWithNPAPI() { FilePath path; // Register Gears, if available. if (PathService::Get(chrome::FILE_GEARS_PLUGIN, &path)) - webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); + NPAPI::PluginList::Singleton()->AddExtraPluginPath(path); } static void LogPluginLoadTime(const TimeDelta &time) { diff --git a/chrome/common/default_plugin.cc b/chrome/common/default_plugin.cc index 3337c7c..bba738b 100644 --- a/chrome/common/default_plugin.cc +++ b/chrome/common/default_plugin.cc @@ -5,13 +5,13 @@ #include "chrome/common/default_plugin.h" #include "chrome/default_plugin/plugin_main.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" namespace chrome { void RegisterInternalDefaultPlugin() { - const webkit::npapi::PluginVersionInfo default_plugin = { - FilePath(webkit::npapi::kDefaultPluginLibraryName), + const NPAPI::PluginVersionInfo default_plugin = { + FilePath(kDefaultPluginLibraryName), L"Default Plug-in", L"Provides functionality for installing third-party plug-ins", L"1", @@ -27,8 +27,7 @@ void RegisterInternalDefaultPlugin() { } }; - webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( - default_plugin); + NPAPI::PluginList::Singleton()->RegisterInternalPlugin(default_plugin); } } // namespace chrome diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc index 4600638..84ab339 100644 --- a/chrome/common/gpu_plugin.cc +++ b/chrome/common/gpu_plugin.cc @@ -9,15 +9,18 @@ #include "base/utf_string_conversions.h" #include "chrome/common/chrome_switches.h" #include "gpu/gpu_plugin/gpu_plugin.h" -#include "webkit/plugins/npapi/plugin_list.h" +#include "webkit/glue/plugins/plugin_list.h" + +#if defined(ENABLE_GPU) +#include "webkit/glue/plugins/plugin_constants_win.h" +#endif namespace chrome { void RegisterInternalGPUPlugin() { #if defined(ENABLE_GPU) - static const std::wstring kWideMimeType = ASCIIToWide( - "application/vnd.google.chrome.gpu-plugin"); - static const webkit::npapi::PluginVersionInfo kGPUPluginInfo = { + static const std::wstring kWideMimeType = ASCIIToWide(kGPUPluginMimeType); + static const NPAPI::PluginVersionInfo kGPUPluginInfo = { FilePath(FILE_PATH_LITERAL("gpu-plugin")), L"GPU Plug-in", L"GPU Rendering Plug-in", @@ -35,8 +38,7 @@ void RegisterInternalGPUPlugin() { }; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableGPUPlugin)) - webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( - kGPUPluginInfo); + NPAPI::PluginList::Singleton()->RegisterInternalPlugin(kGPUPluginInfo); #endif // ENABLE_GPU } diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc index c865a68..d0f8d4a 100644 --- a/chrome/common/render_messages.cc +++ b/chrome/common/render_messages.cc @@ -23,12 +23,12 @@ #include "webkit/blob/blob_data.h" #include "webkit/glue/form_field.h" #include "webkit/glue/password_form.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/resource_loader_bridge.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webcookie.h" #include "webkit/glue/webcursor.h" #include "webkit/glue/webmenuitem.h" -#include "webkit/plugins/npapi/webplugin.h" #if defined(OS_MACOSX) #include "chrome/common/font_descriptor_mac.h" @@ -196,8 +196,8 @@ void ParamTraits::Log(const param_type& p, l->append(""); } -void ParamTraits::Write(Message* m, - const param_type& p) { +void ParamTraits::Write(Message* m, + const param_type& p) { WriteParam(m, p.window); WriteParam(m, p.window_rect); WriteParam(m, p.clip_rect); @@ -206,7 +206,7 @@ void ParamTraits::Write(Message* m, WriteParam(m, p.visible); } -bool ParamTraits::Read( +bool ParamTraits::Read( const Message* m, void** iter, param_type* p) { return ReadParam(m, iter, &p->window) && @@ -217,8 +217,8 @@ bool ParamTraits::Read( ReadParam(m, iter, &p->visible); } -void ParamTraits::Log(const param_type& p, - std::string* l) { +void ParamTraits::Log(const param_type& p, + std::string* l) { l->append("("); LogParam(p.window, l); l->append(", "); @@ -234,24 +234,21 @@ void ParamTraits::Log(const param_type& p, l->append(")"); } -void ParamTraits::Write(Message* m, - const param_type& p) { +void ParamTraits::Write(Message* m, const param_type& p) { WriteParam(m, p.mime_type); WriteParam(m, p.file_extensions); WriteParam(m, p.description); } -bool ParamTraits::Read(const Message* m, - void** iter, - param_type* r) { +bool ParamTraits::Read(const Message* m, void** iter, + param_type* r) { return ReadParam(m, iter, &r->mime_type) && ReadParam(m, iter, &r->file_extensions) && ReadParam(m, iter, &r->description); } -void ParamTraits::Log(const param_type& p, - std::string* l) { +void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); LogParam(p.mime_type, l); l->append(", "); @@ -261,8 +258,7 @@ void ParamTraits::Log(const param_type& p, l->append(")"); } -void ParamTraits::Write(Message* m, - const param_type& p) { +void ParamTraits::Write(Message* m, const param_type& p) { WriteParam(m, p.name); WriteParam(m, p.path); WriteParam(m, p.version); @@ -271,9 +267,8 @@ void ParamTraits::Write(Message* m, WriteParam(m, p.enabled); } -bool ParamTraits::Read(const Message* m, - void** iter, - param_type* r) { +bool ParamTraits::Read(const Message* m, void** iter, + param_type* r) { return ReadParam(m, iter, &r->name) && ReadParam(m, iter, &r->path) && @@ -283,8 +278,7 @@ bool ParamTraits::Read(const Message* m, ReadParam(m, iter, &r->enabled); } -void ParamTraits::Log(const param_type& p, - std::string* l) { +void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); LogParam(p.name, l); l->append(", "); diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 06e597c..6e4e6b9 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -61,15 +61,8 @@ struct ResourceLoadTimingInfo; struct ResourceResponseInfo; struct WebAccessibility; struct WebCookie; -struct WebAccessibility; -} - -namespace webkit { -namespace npapi { struct WebPluginGeometry; -struct WebPluginInfo; -struct WebPluginMimeType; -} +struct WebAccessibility; } struct AudioBuffersState; @@ -84,6 +77,8 @@ struct SyncLoadResult; struct RendererPreferences; struct WebDropData; struct WebMenuItem; +struct WebPluginInfo; +struct WebPluginMimeType; struct WebPreferences; // Forward declarations of structures used to store data for when we have a lot @@ -156,8 +151,8 @@ struct ParamTraits { }; template <> -struct ParamTraits { - typedef webkit::npapi::WebPluginGeometry param_type; +struct ParamTraits { + typedef webkit_glue::WebPluginGeometry param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, void** iter, param_type* p); static void Log(const param_type& p, std::string* l); @@ -165,16 +160,16 @@ struct ParamTraits { // Traits for ViewMsg_GetPlugins_Reply structure to pack/unpack. template <> -struct ParamTraits { - typedef webkit::npapi::WebPluginMimeType param_type; +struct ParamTraits { + typedef WebPluginMimeType param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, void** iter, param_type* r); static void Log(const param_type& p, std::string* l); }; template <> -struct ParamTraits { - typedef webkit::npapi::WebPluginInfo param_type; +struct ParamTraits { + typedef WebPluginInfo param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, void** iter, param_type* r); static void Log(const param_type& p, std::string* l); diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 01fc555..947be93 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -30,8 +30,8 @@ #include "webkit/glue/context_menu.h" #include "webkit/glue/form_data.h" #include "webkit/glue/password_form_dom_manager.h" +#include "webkit/glue/plugins/webplugininfo.h" #include "webkit/glue/webdropdata.h" -#include "webkit/plugins/npapi/webplugininfo.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" @@ -1362,8 +1362,8 @@ IPC_SYNC_MESSAGE_ROUTED2_1(ViewHostMsg_CookiesEnabled, // Used to get the list of plugins IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetPlugins, - bool /* refresh*/, - std::vector /* plugins */) + bool /* refresh*/, + std::vector /* plugins */) // Return information about a plugin for the given URL and MIME // type. If there is no matching plugin, |found| is false. If @@ -1391,7 +1391,7 @@ IPC_SYNC_MESSAGE_CONTROL3_4(ViewHostMsg_GetPluginInfo, GURL /* policy_url */, std::string /* mime_type */, bool /* found */, - webkit::npapi::WebPluginInfo /* plugin info */, + WebPluginInfo /* plugin info */, ContentSetting /* setting */, std::string /* actual_mime_type */) @@ -1535,7 +1535,7 @@ IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_OpenChannelToPlugin, GURL /* url */, std::string /* mime_type */, IPC::ChannelHandle /* channel_handle */, - webkit::npapi::WebPluginInfo /* info */) + WebPluginInfo /* info */) // A renderer sends this to the browser process when it wants to // create a pepper plugin. The browser will create the plugin process if diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h index 911e3ae..7b21a20 100644 --- a/chrome/common/render_messages_params.h +++ b/chrome/common/render_messages_params.h @@ -32,11 +32,11 @@ #include "media/audio/audio_parameters.h" #include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h" #include "webkit/glue/password_form.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/resource_type.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webmenuitem.h" #include "webkit/glue/webpreferences.h" -#include "webkit/plugins/npapi/webplugin.h" // TODO(erg): Split this file into $1_db_params.h, $1_audio_params.h, // $1_print_params.h and $1_render_params.h. @@ -356,7 +356,7 @@ struct ViewHostMsg_UpdateRect_Params { gfx::Rect resizer_rect; // New window locations for plugin child windows. - std::vector plugin_window_moves; + std::vector plugin_window_moves; // The following describes the various bits that may be set in flags: // diff --git a/chrome/default_plugin/DEPS b/chrome/default_plugin/DEPS index 0ba7c46..6e518f99 100644 --- a/chrome/default_plugin/DEPS +++ b/chrome/default_plugin/DEPS @@ -3,5 +3,4 @@ include_rules = [ "+grit", # For generated headers "+libxml", "+webkit/glue", - "+webkit/plugins", ] diff --git a/chrome/default_plugin/plugin_impl_gtk.cc b/chrome/default_plugin/plugin_impl_gtk.cc index b6dc38a..ae7dfb2 100644 --- a/chrome/default_plugin/plugin_impl_gtk.cc +++ b/chrome/default_plugin/plugin_impl_gtk.cc @@ -14,7 +14,7 @@ #include "grit/webkit_strings.h" #include "unicode/locid.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/default_plugin_shared.h" +#include "webkit/glue/plugins/default_plugin_shared.h" // TODO(thakis): Most methods in this class are stubbed out an need to be // implemented. @@ -137,6 +137,6 @@ void PluginInstallerImpl::NotifyPluginStatus(int status) { default_plugin::g_browser->getvalue( instance_, static_cast( - webkit::npapi::default_plugin::kMissingPluginStatusStart + status), + default_plugin::kMissingPluginStatusStart + status), NULL); } diff --git a/chrome/default_plugin/plugin_impl_mac.mm b/chrome/default_plugin/plugin_impl_mac.mm index f964023..0bad41b 100644 --- a/chrome/default_plugin/plugin_impl_mac.mm +++ b/chrome/default_plugin/plugin_impl_mac.mm @@ -17,7 +17,7 @@ #include "grit/webkit_strings.h" #include "unicode/locid.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/default_plugin_shared.h" +#include "webkit/glue/plugins/default_plugin_shared.h" // TODO(thakis): Most methods in this class are stubbed out and need to be // implemented. @@ -194,6 +194,6 @@ void PluginInstallerImpl::NotifyPluginStatus(int status) { default_plugin::g_browser->getvalue( instance_, static_cast( - webkit::npapi::default_plugin::kMissingPluginStatusStart + status), + default_plugin::kMissingPluginStatusStart + status), NULL); } diff --git a/chrome/default_plugin/plugin_impl_win.cc b/chrome/default_plugin/plugin_impl_win.cc index cb767b0..e9346c6 100644 --- a/chrome/default_plugin/plugin_impl_win.cc +++ b/chrome/default_plugin/plugin_impl_win.cc @@ -15,7 +15,7 @@ #include "grit/webkit_strings.h" #include "unicode/locid.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/default_plugin_shared.h" +#include "webkit/glue/plugins/default_plugin_shared.h" static const int TOOLTIP_MAX_WIDTH = 500; @@ -250,8 +250,7 @@ void PluginInstallerImpl::URLNotify(const char* url, NPReason reason) { if (plugin_available) { DVLOG(1) << "Plugin available for mime type " << mime_type_; DisplayAvailablePluginStatus(); - NotifyPluginStatus( - webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE); + NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); } else { DLOG(WARNING) << "No plugin available for mime type " << mime_type_; DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); @@ -261,8 +260,7 @@ void PluginInstallerImpl::URLNotify(const char* url, NPReason reason) { int16 PluginInstallerImpl::NPP_HandleEvent(void* event) { NPEvent* npp_event = static_cast(event); - if (npp_event->event == - webkit::npapi::default_plugin::kInstallMissingPluginMessage) { + if (npp_event->event == default_plugin::kInstallMissingPluginMessage) { // We could get this message because InfoBar may not be in sync with our // internal processing. So we need to check the status. if (plugin_installer_state() == PluginListDownloaded) { @@ -529,8 +527,7 @@ LRESULT PluginInstallerImpl::OnLButtonDown(UINT message, WPARAM wparam, return 0; if (plugin_installer_state() == PluginListDownloaded) { ShowInstallDialog(); - NotifyPluginStatus( - webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD); + NotifyPluginStatus(default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD); } else if (plugin_installer_state_ == PluginInstallerLaunchSuccess) { DCHECK(default_plugin::g_browser); DCHECK(default_plugin::g_browser->geturl); @@ -645,6 +642,6 @@ void PluginInstallerImpl::NotifyPluginStatus(int status) { default_plugin::g_browser->getvalue( instance_, static_cast( - webkit::npapi::default_plugin::kMissingPluginStatusStart + status), + default_plugin::kMissingPluginStatusStart + status), NULL); } diff --git a/chrome/plugin/DEPS b/chrome/plugin/DEPS index 15434bf..3517180 100644 --- a/chrome/plugin/DEPS +++ b/chrome/plugin/DEPS @@ -5,7 +5,7 @@ include_rules = [ "+skia/ext", "+third_party/npapi", "+webkit/glue", - "+webkit/plugins", + "+webkit/glue/plugins", "+grit", # For generated headers ] diff --git a/chrome/plugin/chrome_plugin_host.cc b/chrome/plugin/chrome_plugin_host.cc index 8458e25..22b3da9 100644 --- a/chrome/plugin/chrome_plugin_host.cc +++ b/chrome/plugin/chrome_plugin_host.cc @@ -25,7 +25,7 @@ #include "net/base/upload_data.h" #include "net/http/http_response_headers.h" #include "webkit/appcache/appcache_interfaces.h" -#include "webkit/plugins/npapi/plugin_instance.h" +#include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/resource_loader_bridge.h" #include "webkit/glue/resource_type.h" #include "webkit/glue/webkit_glue.h" @@ -415,8 +415,8 @@ CPBrowsingContext STDCALL CPB_GetBrowsingContextFromNPP(NPP npp) { if (!npp) return CPERR_INVALID_PARAMETER; - webkit::npapi::PluginInstance* instance = - static_cast(npp->ndata); + NPAPI::PluginInstance* instance = + static_cast(npp->ndata); WebPluginProxy* webplugin = static_cast(instance->webplugin()); diff --git a/chrome/plugin/npobject_proxy.cc b/chrome/plugin/npobject_proxy.cc index 0b7ff45..f245151 100644 --- a/chrome/plugin/npobject_proxy.cc +++ b/chrome/plugin/npobject_proxy.cc @@ -9,7 +9,7 @@ #include "chrome/plugin/plugin_channel.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/plugin_instance.h" +#include "webkit/glue/plugins/plugin_instance.h" using WebKit::WebBindings; @@ -460,8 +460,8 @@ bool NPObjectProxy::NPNEvaluate(NPP npp, bool popups_allowed = false; if (npp) { - webkit::npapi::PluginInstance* plugin_instance = - reinterpret_cast(npp->ndata); + NPAPI::PluginInstance* plugin_instance = + reinterpret_cast(npp->ndata); if (plugin_instance) popups_allowed = plugin_instance->popups_allowed(); } diff --git a/chrome/plugin/npobject_stub.cc b/chrome/plugin/npobject_stub.cc index e0a8436..c711756 100644 --- a/chrome/plugin/npobject_stub.cc +++ b/chrome/plugin/npobject_stub.cc @@ -12,7 +12,7 @@ #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npruntime.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" -#include "webkit/plugins/npapi/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_constants_win.h" using WebKit::WebBindings; @@ -243,7 +243,7 @@ void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name, PluginThread::current()->plugin_path().BaseName().value()); static NPIdentifier fullscreen = WebBindings::getStringIdentifier("fullScreen"); - if (filename == webkit::npapi::kNewWMPPlugin && id == fullscreen) { + if (filename == kNewWMPPlugin && id == fullscreen) { // Workaround for bug 15985, which is if Flash causes WMP to go // full screen a deadlock can occur when WMP calls SetFocus. NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, true); diff --git a/chrome/plugin/npobject_util.cc b/chrome/plugin/npobject_util.cc index 60324cf..0c54a33 100644 --- a/chrome/plugin/npobject_util.cc +++ b/chrome/plugin/npobject_util.cc @@ -10,7 +10,7 @@ #include "chrome/plugin/plugin_channel_base.h" #include "third_party/npapi/bindings/nphostapi.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" -#include "webkit/plugins/npapi/plugin_host.h" +#include "webkit/glue/plugins/plugin_host.h" #include "webkit/glue/webkit_glue.h" using WebKit::WebBindings; @@ -129,7 +129,7 @@ NPNetscapeFuncs *GetHostFunctions() { void PatchNPNFunctions() { g_plugin_process = true; NPNetscapeFuncs* funcs = GetHostFunctions(); - webkit::npapi::PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs); + NPAPI::PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs); } bool IsPluginProcess() { diff --git a/chrome/plugin/plugin_channel.cc b/chrome/plugin/plugin_channel.cc index bc5e61e..b3b12951 100644 --- a/chrome/plugin/plugin_channel.cc +++ b/chrome/plugin/plugin_channel.cc @@ -16,7 +16,7 @@ #include "chrome/plugin/plugin_thread.h" #include "chrome/plugin/webplugin_delegate_stub.h" #include "chrome/plugin/webplugin_proxy.h" -#include "webkit/plugins/npapi/plugin_instance.h" +#include "webkit/glue/plugins/plugin_instance.h" #if defined(OS_POSIX) #include "base/eintr_wrapper.h" @@ -256,12 +256,12 @@ void PluginChannel::OnClearSiteData(uint64 flags, bool success = false; CommandLine* command_line = CommandLine::ForCurrentProcess(); FilePath path = command_line->GetSwitchValuePath(switches::kPluginPath); - scoped_refptr plugin_lib( - webkit::npapi::PluginLib::CreatePluginLib(path)); + scoped_refptr plugin_lib( + NPAPI::PluginLib::CreatePluginLib(path)); if (plugin_lib.get()) { NPError err = plugin_lib->NP_Initialize(); if (err == NPERR_NO_ERROR) { - scoped_refptr instance( + scoped_refptr instance( plugin_lib->CreateInstance(std::string())); const char* domain_str = domain.empty() ? NULL : domain.c_str(); diff --git a/chrome/plugin/plugin_interpose_util_mac.mm b/chrome/plugin/plugin_interpose_util_mac.mm index 7299d4b..45df449 100644 --- a/chrome/plugin/plugin_interpose_util_mac.mm +++ b/chrome/plugin/plugin_interpose_util_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,7 @@ #include "chrome/common/plugin_messages.h" #include "chrome/plugin/plugin_thread.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" namespace mac_plugin_interposing { @@ -32,7 +32,7 @@ void SwitchToPluginProcess() { __attribute__((visibility("default"))) OpaquePluginRef GetActiveDelegate() { - return webkit::npapi::WebPluginDelegateImpl::GetActiveDelegate(); + return WebPluginDelegateImpl::GetActiveDelegate(); } __attribute__((visibility("default"))) @@ -72,15 +72,13 @@ void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds) { __attribute__((visibility("default"))) void NotifyPluginOfSetThemeCursor(OpaquePluginRef delegate, ThemeCursor cursor) { - static_cast(delegate)->SetThemeCursor( - cursor); + static_cast(delegate)->SetThemeCursor(cursor); } __attribute__((visibility("default"))) void NotifyPluginOfSetCursor(OpaquePluginRef delegate, const Cursor* cursor) { - static_cast(delegate)->SetCursor( - cursor); + static_cast(delegate)->SetCursor(cursor); } void NotifyPluginOfSetCursorVisibility(bool visibility) { @@ -93,8 +91,7 @@ void NotifyPluginOfSetCursorVisibility(bool visibility) { __attribute__((visibility("default"))) bool GetPluginWindowHasFocus(const OpaquePluginRef delegate) { - return static_cast( - delegate)->GetWindowHasFocus(); + return static_cast(delegate)->GetWindowHasFocus(); } } // namespace mac_plugin_interposing @@ -240,8 +237,7 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) { - (void)chromePlugin_set { OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate(); if (delegate) { - static_cast(delegate)->SetNSCursor( - self); + static_cast(delegate)->SetNSCursor(self); return; } [self chromePlugin_set]; diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index 8edcbbd..7e2b921 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -29,9 +29,9 @@ #include "chrome/renderer/render_thread.h" #include "ipc/ipc_channel_handle.h" #include "net/base/net_errors.h" +#include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/plugin_lib.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" #if defined(TOOLKIT_USES_GTK) #include "gfx/gtk_util.h" @@ -86,8 +86,8 @@ PluginThread::PluginThread() ChromePluginLib::Create(plugin_path_, GetCPBrowserFuncsForPlugin()); - scoped_refptr plugin( - webkit::npapi::PluginLib::CreatePluginLib(plugin_path_)); + scoped_refptr plugin( + NPAPI::PluginLib::CreatePluginLib(plugin_path_)); if (plugin.get()) { plugin->NP_Initialize(); @@ -115,7 +115,7 @@ PluginThread::~PluginThread() { preloaded_plugin_module_ = NULL; } PluginChannelBase::CleanupChannels(); - webkit::npapi::PluginLib::UnloadAllPlugins(); + NPAPI::PluginLib::UnloadAllPlugins(); ChromePluginLib::UnloadAllPlugins(); if (webkit_glue::ShouldForcefullyTerminatePluginProcess()) diff --git a/chrome/plugin/plugin_thread.h b/chrome/plugin/plugin_thread.h index 4d24e3c..99d07ed 100644 --- a/chrome/plugin/plugin_thread.h +++ b/chrome/plugin/plugin_thread.h @@ -11,7 +11,7 @@ #include "build/build_config.h" #include "chrome/common/child_thread.h" #include "chrome/plugin/plugin_channel.h" -#include "webkit/plugins/npapi/plugin_lib.h" +#include "webkit/glue/plugins/plugin_lib.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" diff --git a/chrome/plugin/webplugin_accelerated_surface_proxy_mac.h b/chrome/plugin/webplugin_accelerated_surface_proxy_mac.h index ee4df63..8764ab9 100644 --- a/chrome/plugin/webplugin_accelerated_surface_proxy_mac.h +++ b/chrome/plugin/webplugin_accelerated_surface_proxy_mac.h @@ -6,7 +6,7 @@ #define CHROME_PLUGIN_WEBPLUGIN_ACCELERATED_SURFACE_PROXY_H_ #pragma once -#include "webkit/plugins/npapi/webplugin_accelerated_surface_mac.h" +#include "webkit/glue/plugins/webplugin_accelerated_surface_mac.h" class WebPluginProxy; class AcceleratedSurface; @@ -14,7 +14,7 @@ class AcceleratedSurface; // Out-of-process implementation of WebPluginAcceleratedSurface that proxies // calls through a WebPluginProxy. class WebPluginAcceleratedSurfaceProxy - : public webkit::npapi::WebPluginAcceleratedSurface { + : public webkit_glue::WebPluginAcceleratedSurface { public: // Creates a new WebPluginAcceleratedSurfaceProxy that uses plugin_proxy // to proxy calls. plugin_proxy must outlive this object. diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 0540adf..ff0652d 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -20,7 +20,7 @@ #include "skia/ext/platform_device.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" #include "webkit/glue/webcursor.h" #if defined(ENABLE_GPU) @@ -29,15 +29,13 @@ using WebKit::WebBindings; using WebKit::WebCursorInfo; -using webkit::npapi::WebPlugin; -using webkit::npapi::WebPluginResourceClient; +using webkit_glue::WebPlugin; +using webkit_glue::WebPluginResourceClient; class FinishDestructionTask : public Task { public: - FinishDestructionTask(webkit::npapi::WebPluginDelegateImpl* delegate, - WebPlugin* webplugin) - : delegate_(delegate), webplugin_(webplugin) { - } + FinishDestructionTask(WebPluginDelegateImpl* delegate, WebPlugin* webplugin) + : delegate_(delegate), webplugin_(webplugin) { } void Run() { // WebPlugin must outlive WebPluginDelegate. @@ -48,8 +46,8 @@ class FinishDestructionTask : public Task { } private: - webkit::npapi::WebPluginDelegateImpl* delegate_; - webkit::npapi::WebPlugin* webplugin_; + WebPluginDelegateImpl* delegate_; + WebPlugin* webplugin_; }; WebPluginDelegateStub::WebPluginDelegateStub( @@ -187,8 +185,7 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params, webplugin_ = new WebPluginProxy( channel_, instance_id_, page_url_, params.containing_window, params.host_render_view_routing_id); - delegate_ = webkit::npapi::WebPluginDelegateImpl::Create( - path, mime_type_, parent); + delegate_ = WebPluginDelegateImpl::Create(path, mime_type_, parent); if (delegate_) { webplugin_->set_delegate(delegate_); *result = delegate_->Initialize(params.url, diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index c310467..cbd2c97 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -29,11 +29,7 @@ namespace WebKit { class WebInputEvent; } -namespace webkit { -namespace npapi { class WebPluginDelegateImpl; -} -} // Converts the IPC messages from WebPluginDelegateProxy into calls to the // actual WebPluginDelegateImpl object. @@ -115,7 +111,7 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, scoped_refptr channel_; - webkit::npapi::WebPluginDelegateImpl* delegate_; + WebPluginDelegateImpl* delegate_; WebPluginProxy* webplugin_; bool in_destructor_; diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 498df98..bb77108 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -34,17 +34,16 @@ #endif #include "skia/ext/platform_device.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" #if defined(USE_X11) #include "app/x11_util_internal.h" #endif using WebKit::WebBindings; - -using webkit::npapi::WebPluginResourceClient; +using webkit_glue::WebPluginResourceClient; #if defined(OS_MACOSX) -using webkit::npapi::WebPluginAcceleratedSurface; +using webkit_glue::WebPluginAcceleratedSurface; #endif typedef std::map ContextMap; @@ -324,8 +323,7 @@ void WebPluginProxy::HandleURLRequest(const char* url, // Please refer to https://bugzilla.mozilla.org/show_bug.cgi?id=366082 // for more details on this. if (delegate_->GetQuirks() & - webkit::npapi::WebPluginDelegateImpl:: - PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS) { + WebPluginDelegateImpl::PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS) { GURL request_url(url); if (!request_url.SchemeIs(chrome::kHttpScheme) && !request_url.SchemeIs(chrome::kHttpsScheme) && diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 2a1f1aee..66b396c 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -24,23 +24,17 @@ #include "chrome/common/chrome_plugin_api.h" #include "googleurl/src/gurl.h" #include "ipc/ipc_message.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" class PluginChannel; - -namespace webkit { -namespace npapi { class WebPluginDelegateImpl; -} -} - #if defined(OS_MACOSX) class WebPluginAcceleratedSurfaceProxy; #endif // This is an implementation of WebPlugin that proxies all calls to the // renderer. -class WebPluginProxy : public webkit::npapi::WebPlugin { +class WebPluginProxy : public webkit_glue::WebPlugin { public: // Creates a new proxy for WebPlugin, using the given sender to send the // marshalled WebPlugin calls. @@ -51,7 +45,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { int host_render_view_routing_id); ~WebPluginProxy(); - void set_delegate(webkit::npapi::WebPluginDelegateImpl* d) { delegate_ = d; } + void set_delegate(WebPluginDelegateImpl* d) { delegate_ = d; } // WebPlugin overrides virtual void SetWindow(gfx::PluginWindowHandle window); @@ -99,7 +93,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { // Returns a WebPluginResourceClient object given its id, or NULL if no // object with that id exists. - webkit::npapi::WebPluginResourceClient* GetResourceClient(int id); + webkit_glue::WebPluginResourceClient* GetResourceClient(int id); // Returns the id of the renderer that contains this plugin. int GetRendererId(); @@ -117,7 +111,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { // Notification received on a plugin issued resource request creation. void OnResourceCreated(int resource_id, - webkit::npapi::WebPluginResourceClient* client); + webkit_glue::WebPluginResourceClient* client); virtual void HandleURLRequest(const char* url, const char* method, @@ -143,7 +137,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { virtual void SetDeferResourceLoading(unsigned long resource_id, bool defer); virtual bool IsOffTheRecord(); virtual void ResourceClientDeleted( - webkit::npapi::WebPluginResourceClient* resource_client); + webkit_glue::WebPluginResourceClient* resource_client); gfx::NativeViewId containing_window() { return containing_window_; } #if defined(OS_MACOSX) @@ -151,7 +145,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { virtual void BindFakePluginWindowHandle(bool opaque); - virtual webkit::npapi::WebPluginAcceleratedSurface* GetAcceleratedSurface(); + virtual webkit_glue::WebPluginAcceleratedSurface* GetAcceleratedSurface(); // Tell the browser (via the renderer) to invalidate because the // accelerated buffers have changed. @@ -195,7 +189,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { const TransportDIB::Handle& background_buffer, const gfx::Rect& window_rect); - typedef base::hash_map + typedef base::hash_map ResourceClientMap; ResourceClientMap resource_clients_; @@ -204,7 +198,7 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { uint32 cp_browsing_context_; NPObject* window_npobject_; NPObject* plugin_element_; - webkit::npapi::WebPluginDelegateImpl* delegate_; + WebPluginDelegateImpl* delegate_; gfx::Rect damaged_rect_; bool waiting_for_paint_; gfx::NativeViewId containing_window_; diff --git a/chrome/renderer/blocked_plugin.cc b/chrome/renderer/blocked_plugin.cc index 68af8f8..e3d2a3a 100644 --- a/chrome/renderer/blocked_plugin.cc +++ b/chrome/renderer/blocked_plugin.cc @@ -22,9 +22,9 @@ #include "third_party/WebKit/WebKit/chromium/public/WebPoint.h" #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" +#include "webkit/glue/plugins/plugin_group.h" +#include "webkit/glue/plugins/webview_plugin.h" #include "webkit/glue/webpreferences.h" -#include "webkit/plugins/npapi/plugin_group.h" -#include "webkit/plugins/npapi/webview_plugin.h" using WebKit::WebContextMenuData; using WebKit::WebFrame; @@ -42,7 +42,7 @@ static const unsigned kMenuActionRemove = 2; BlockedPlugin::BlockedPlugin(RenderView* render_view, WebFrame* frame, - const webkit::npapi::PluginGroup& info, + const PluginGroup& info, const WebPluginParams& params, const WebPreferences& preferences, int template_id, @@ -65,10 +65,10 @@ BlockedPlugin::BlockedPlugin(RenderView* render_view, std::string html_data = jstemplate_builder::GetTemplatesHtml( template_html, &values, "t"); - plugin_ = webkit::npapi::WebViewPlugin::Create(this, - preferences, - html_data, - GURL(kBlockedPluginDataURL)); + plugin_ = WebViewPlugin::Create(this, + preferences, + html_data, + GURL(kBlockedPluginDataURL)); registrar_.Add(this, NotificationType::SHOULD_LOAD_PLUGINS, diff --git a/chrome/renderer/blocked_plugin.h b/chrome/renderer/blocked_plugin.h index 7b616bf..53859bc 100644 --- a/chrome/renderer/blocked_plugin.h +++ b/chrome/renderer/blocked_plugin.h @@ -11,32 +11,26 @@ #include "chrome/renderer/custom_menu_listener.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" #include "webkit/glue/cpp_bound_class.h" -#include "webkit/plugins/npapi/webview_plugin.h" +#include "webkit/glue/plugins/webview_plugin.h" class GURL; -class RenderView; - - -namespace webkit { -namespace npapi { class PluginGroup; -} -} +class RenderView; class BlockedPlugin : public CppBoundClass, - public webkit::npapi::WebViewPlugin::Delegate, + public WebViewPlugin::Delegate, public NotificationObserver, public CustomMenuListener { public: BlockedPlugin(RenderView* render_view, WebKit::WebFrame* frame, - const webkit::npapi::PluginGroup& info, + const PluginGroup& info, const WebKit::WebPluginParams& params, const WebPreferences& settings, int template_id, const string16& message); - webkit::npapi::WebViewPlugin* plugin() { return plugin_; } + WebViewPlugin* plugin() { return plugin_; } // WebViewPlugin::Delegate methods: virtual void BindWebFrame(WebKit::WebFrame* frame); @@ -68,7 +62,7 @@ class BlockedPlugin : public CppBoundClass, RenderView* render_view_; WebKit::WebFrame* frame_; WebKit::WebPluginParams plugin_params_; - webkit::npapi::WebViewPlugin* plugin_; + WebViewPlugin* plugin_; // The name of the plugin that was blocked. string16 name_; diff --git a/chrome/renderer/pepper_devices.cc b/chrome/renderer/pepper_devices.cc index 407d454..aa98711 100644 --- a/chrome/renderer/pepper_devices.cc +++ b/chrome/renderer/pepper_devices.cc @@ -9,8 +9,8 @@ #include "chrome/renderer/webplugin_delegate_pepper.h" #include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "webkit/plugins/npapi/plugin_instance.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin.h" namespace { diff --git a/chrome/renderer/pepper_devices_browsertest.cc b/chrome/renderer/pepper_devices_browsertest.cc index 963975c..e8e0bbe 100644 --- a/chrome/renderer/pepper_devices_browsertest.cc +++ b/chrome/renderer/pepper_devices_browsertest.cc @@ -18,9 +18,9 @@ #include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h" #include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h" #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" -#include "webkit/plugins/npapi/plugin_instance.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugin_impl.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugin_impl.h" class PepperDeviceTest; @@ -135,9 +135,9 @@ class PepperDeviceTest : public RenderViewTest { virtual void SetUp(); virtual void TearDown(); - webkit::npapi::PluginVersionInfo version_info_; + NPAPI::PluginVersionInfo version_info_; - scoped_ptr plugin_; + scoped_ptr plugin_; WebPluginDelegatePepper* pepper_plugin_; // FIXME(brettw): check lifetime. }; @@ -147,7 +147,7 @@ PepperDeviceTest::PepperDeviceTest() { version_info_.file_description = ASCIIToWide("Pepper device test plugin"); version_info_.file_version = ASCIIToWide("1"); version_info_.mime_types = ASCIIToWide(kTestPluginMimeType); - webkit::npapi::PluginEntryPoints entry_points = { + NPAPI::PluginEntryPoints entry_points = { #if !defined(OS_POSIX) || defined(OS_MACOSX) NP_GetEntryPoints, #endif @@ -163,14 +163,14 @@ PepperDeviceTest::~PepperDeviceTest() { void PepperDeviceTest::SetUp() { RenderViewTest::SetUp(); - webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(version_info_); + NPAPI::PluginList::Singleton()->RegisterInternalPlugin(version_info_); // Create the WebKit plugin with no delegates (this seems to work // sufficiently for the test). WebKit::WebPluginParams params; - plugin_.reset(new webkit::npapi::WebPluginImpl( + plugin_.reset(new webkit_glue::WebPluginImpl( NULL, params, FilePath(), std::string(), - base::WeakPtr())); + base::WeakPtr())); // Create a pepper plugin for the RenderView. pepper_plugin_ = WebPluginDelegatePepper::Create( @@ -201,8 +201,7 @@ void PepperDeviceTest::TearDown() { if (pepper_plugin_) pepper_plugin_->PluginDestroyed(); - webkit::npapi::PluginList::Singleton()->UnregisterInternalPlugin( - version_info_.path); + NPAPI::PluginList::Singleton()->UnregisterInternalPlugin(version_info_.path); RenderViewTest::TearDown(); } diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc index e223202..87aa127 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.cc +++ b/chrome/renderer/pepper_plugin_delegate_impl.cc @@ -41,7 +41,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "webkit/fileapi/file_system_callback_dispatcher.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/plugins/ppapi/ppb_file_io_impl.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" diff --git a/chrome/renderer/pepper_scrollbar_widget.cc b/chrome/renderer/pepper_scrollbar_widget.cc index c4878a3..63c446a 100644 --- a/chrome/renderer/pepper_scrollbar_widget.cc +++ b/chrome/renderer/pepper_scrollbar_widget.cc @@ -11,7 +11,7 @@ #include "skia/ext/platform_canvas.h" #include "skia/ext/platform_device.h" #include "third_party/WebKit/WebKit/chromium/public/WebScrollbar.h" -#include "webkit/plugins/npapi/plugin_instance.h" +#include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/webkit_glue.h" using WebKit::WebInputEvent; diff --git a/chrome/renderer/pepper_widget.cc b/chrome/renderer/pepper_widget.cc index 176510f..ba37f87 100644 --- a/chrome/renderer/pepper_widget.cc +++ b/chrome/renderer/pepper_widget.cc @@ -9,9 +9,9 @@ #include "chrome/renderer/pepper_scrollbar_widget.h" #include "chrome/renderer/webplugin_delegate_pepper.h" #include "skia/ext/platform_canvas.h" -#include "webkit/plugins/npapi/plugin_instance.h" -#include "webkit/plugins/npapi/webplugin.h" -#include "webkit/plugins/npapi/webplugin_delegate.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/plugins/webplugin_delegate.h" #if defined(OS_WIN) #include "base/win/windows_version.h" @@ -57,8 +57,8 @@ NPError NPPaintWidget(NPP instance, if (iter == g_widgets.Get().end()) return NPERR_INVALID_PARAM; - webkit::npapi::PluginInstance* plugin = - static_cast(instance->ndata); + NPAPI::PluginInstance* plugin = + static_cast(instance->ndata); WebPluginDelegatePepper* delegate = static_cast(plugin->webplugin()->delegate()); Graphics2DDeviceContext* gdc = delegate->GetGraphicsContext(context); @@ -135,8 +135,8 @@ void PepperWidget::Init(NPP instance, int id) { } void PepperWidget::WidgetPropertyChanged(NPWidgetProperty property) { - webkit::npapi::PluginInstance* instance = - static_cast(instance_->ndata); + NPAPI::PluginInstance* instance = + static_cast(instance_->ndata); NPPExtensions* extensions = NULL; instance->NPP_GetValue(NPPVPepperExtensions, &extensions); if (!extensions) diff --git a/chrome/renderer/render_process_impl.cc b/chrome/renderer/render_process_impl.cc index 495a234..1396713 100644 --- a/chrome/renderer/render_process_impl.cc +++ b/chrome/renderer/render_process_impl.cc @@ -35,8 +35,8 @@ #include "native_client/src/shared/imc/nacl_imc.h" #include "native_client/src/trusted/plugin/nacl_entry_points.h" #include "skia/ext/platform_canvas.h" -#include "webkit/plugins/npapi/plugin_instance.h" -#include "webkit/plugins/npapi/plugin_lib.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/webkit_glue.h" #if defined(OS_MACOSX) diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 5dd3359..2c50d8e 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -172,18 +172,18 @@ #include "webkit/glue/image_resource_fetcher.h" #include "webkit/glue/media/video_renderer_impl.h" #include "webkit/glue/password_form_dom_manager.h" +#include "webkit/glue/plugins/default_plugin_shared.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" +#include "webkit/glue/plugins/webplugin_impl.h" +#include "webkit/glue/plugins/webview_plugin.h" #include "webkit/glue/resource_fetcher.h" #include "webkit/glue/site_isolation_metrics.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webdropdata.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/webmediaplayer_impl.h" -#include "webkit/plugins/npapi/default_plugin_shared.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/webplugin_delegate.h" -#include "webkit/plugins/npapi/webplugin_delegate_impl.h" -#include "webkit/plugins/npapi/webplugin_impl.h" -#include "webkit/plugins/npapi/webview_plugin.h" #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h" #if defined(OS_WIN) @@ -842,7 +842,7 @@ void RenderView::PluginCrashed(const FilePath& plugin_path) { WebPlugin* RenderView::CreatePluginNoCheck(WebFrame* frame, const WebPluginParams& params) { - webkit::npapi::WebPluginInfo info; + WebPluginInfo info; bool found; ContentSetting setting; std::string mime_type; @@ -2026,15 +2026,14 @@ void RenderView::OnMissingPluginStatus( #if defined(OS_WIN) if (!first_default_plugin_) { // Show the InfoBar for the first available plugin. - if (status == webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE) { + if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) { first_default_plugin_ = delegate->AsWeakPtr(); Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); } } else { // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar) // to start the download/install. - if (status == - webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) { + if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) { Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status)); } } @@ -2755,7 +2754,7 @@ WebPlugin* RenderView::createPlugin(WebFrame* frame, bool found = false; ContentSetting plugin_setting = CONTENT_SETTING_DEFAULT; CommandLine* cmd = CommandLine::ForCurrentProcess(); - webkit::npapi::WebPluginInfo info; + WebPluginInfo info; GURL url(params.url); std::string actual_mime_type; Send(new ViewHostMsg_GetPluginInfo(url, @@ -2770,8 +2769,8 @@ WebPlugin* RenderView::createPlugin(WebFrame* frame, return NULL; DCHECK(plugin_setting != CONTENT_SETTING_DEFAULT); - const webkit::npapi::PluginGroup* group = - webkit::npapi::PluginList::Singleton()->GetPluginGroup(info); + const PluginGroup* group = + NPAPI::PluginList::Singleton()->GetPluginGroup(info); DCHECK(group != NULL); if (cmd->HasSwitch(switches::kBlockOutdatedPlugins) && @@ -2790,7 +2789,7 @@ WebPlugin* RenderView::createPlugin(WebFrame* frame, ContentSetting host_setting = current_content_settings_.settings[CONTENT_SETTINGS_TYPE_PLUGINS]; - if (info.path.value() == webkit::npapi::kDefaultPluginLibraryName || + if (info.path.value() == kDefaultPluginLibraryName || plugin_setting == CONTENT_SETTING_ALLOW || host_setting == CONTENT_SETTING_ALLOW) { scoped_refptr pepper_module( @@ -3940,7 +3939,7 @@ void RenderView::openFileSystem( // webkit_glue::WebPluginPageDelegate ----------------------------------------- -webkit::npapi::WebPluginDelegate* RenderView::CreatePluginDelegate( +webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( const FilePath& file_path, const std::string& mime_type) { if (!PluginChannelHost::IsListening()) @@ -4008,7 +4007,7 @@ webkit::npapi::WebPluginDelegate* RenderView::CreatePluginDelegate( return pepper_plugin; } else { #if defined(OS_WIN) // In-proc plugins aren't supported on Linux or Mac. - return webkit::npapi::WebPluginDelegateImpl::Create( + return WebPluginDelegateImpl::Create( file_path, mime_type, gfx::NativeViewFromId(host_window_)); #else NOTIMPLEMENTED(); @@ -4035,7 +4034,7 @@ void RenderView::WillDestroyPluginWindow(gfx::PluginWindowHandle window) { CleanupWindowInPluginMoves(window); } -void RenderView::DidMovePlugin(const webkit::npapi::WebPluginGeometry& move) { +void RenderView::DidMovePlugin(const webkit_glue::WebPluginGeometry& move) { SchedulePluginMove(move); } @@ -4437,19 +4436,18 @@ WebPlugin* RenderView::CreatePepperPlugin( pepper_module, params, pepper_delegate_.AsWeakPtr()); } -WebPlugin* RenderView::CreateNPAPIPlugin( - WebFrame* frame, - const WebPluginParams& params, - const FilePath& path, - const std::string& mime_type) { - return new webkit::npapi::WebPluginImpl( +WebPlugin* RenderView::CreateNPAPIPlugin(WebFrame* frame, + const WebPluginParams& params, + const FilePath& path, + const std::string& mime_type) { + return new webkit_glue::WebPluginImpl( frame, params, path, mime_type, AsWeakPtr()); } WebPlugin* RenderView::CreatePluginPlaceholder( WebFrame* frame, const WebPluginParams& params, - const webkit::npapi::PluginGroup& group, + const PluginGroup& group, int resource_id, int message_id) { // |blocked_plugin| will delete itself when the WebViewPlugin diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index af7b969..d7589dc 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -43,8 +43,8 @@ #include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h" #include "third_party/WebKit/WebKit/chromium/public/WebViewClient.h" #include "third_party/WebKit/WebKit/chromium/public/WebNavigationType.h" +#include "webkit/glue/plugins/webplugin_page_delegate.h" #include "webkit/glue/webpreferences.h" -#include "webkit/plugins/npapi/webplugin_page_delegate.h" #if defined(OS_WIN) // RenderView is a diamond-shaped hierarchy, with WebWidgetClient at the root. @@ -74,6 +74,7 @@ class NotificationProvider; class PageClickTracker; class PasswordAutocompleteManager; class PepperDeviceTest; +class PluginGroup; class PrintWebViewHelper; class RenderViewVisitor; class SkBitmap; @@ -96,16 +97,12 @@ class Rect; } namespace webkit { - -namespace npapi { -class PluginGroup; -} // namespace npapi - namespace ppapi { + class PluginInstance; class FullscreenContainer; -} // namespace ppapi +} // namespace ppapi } // namespace webkit namespace safe_browsing { @@ -174,7 +171,7 @@ class RenderView : public RenderWidget, public WebKit::WebViewClient, public WebKit::WebFrameClient, public WebKit::WebPageSerializerClient, - public webkit::npapi::WebPluginPageDelegate, + public webkit_glue::WebPluginPageDelegate, public base::SupportsWeakPtr { public: // Creates a new RenderView. The parent_hwnd specifies a HWND to use as the @@ -653,12 +650,12 @@ class RenderView : public RenderWidget, // webkit_glue::WebPluginPageDelegate implementation ------------------------- - virtual webkit::npapi::WebPluginDelegate* CreatePluginDelegate( + virtual webkit_glue::WebPluginDelegate* CreatePluginDelegate( const FilePath& file_path, const std::string& mime_type); virtual void CreatedPluginWindow(gfx::PluginWindowHandle handle); virtual void WillDestroyPluginWindow(gfx::PluginWindowHandle handle); - virtual void DidMovePlugin(const webkit::npapi::WebPluginGeometry& move); + virtual void DidMovePlugin(const webkit_glue::WebPluginGeometry& move); virtual void DidStartLoadingForPlugin(); virtual void DidStopLoadingForPlugin(); virtual void ShowModalHTMLDialogForPlugin( @@ -1029,7 +1026,7 @@ class RenderView : public RenderWidget, WebKit::WebPlugin* CreatePluginPlaceholder( WebKit::WebFrame* frame, const WebKit::WebPluginParams& params, - const webkit::npapi::PluginGroup& group, + const PluginGroup& group, int resource_id, int message_id); @@ -1342,7 +1339,7 @@ class RenderView : public RenderWidget, // Remember the first uninstalled plugin, so that we can ask the plugin // to install itself when user clicks on the info bar. - base::WeakPtr first_default_plugin_; + base::WeakPtr first_default_plugin_; PepperPluginDelegateImpl pepper_delegate_; diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 041fcd9..13c194d 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -27,8 +27,8 @@ #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" #include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/webplugin.h" #if defined(OS_POSIX) #include "ipc/ipc_channel_posix.h" @@ -955,7 +955,7 @@ void RenderWidget::resetInputMethod() { } void RenderWidget::SchedulePluginMove( - const webkit::npapi::WebPluginGeometry& move) { + const webkit_glue::WebPluginGeometry& move) { size_t i = 0; for (; i < plugin_window_moves_.size(); ++i) { if (plugin_window_moves_[i].window == move.window) { diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 92826e9..0fd6634 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -46,11 +46,9 @@ class WebWidget; struct WebPopupMenuInfo; } -namespace webkit { -namespace npapi { +namespace webkit_glue { struct WebPluginGeometry; } -} // RenderWidget provides a communication bridge between a WebWidget and // a RenderWidgetHost, the latter of which lives in a different process. @@ -113,7 +111,7 @@ class RenderWidget : public IPC::Channel::Listener, // 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 webkit::npapi::WebPluginGeometry& move); + void SchedulePluginMove(const webkit_glue::WebPluginGeometry& move); // Called when a plugin window has been destroyed, to make sure the currently // pending moves don't try to reference it. @@ -339,7 +337,7 @@ class RenderWidget : public IPC::Channel::Listener, WebKit::WebPopupType popup_type_; // Holds all the needed plugin window moves for a scroll. - typedef std::vector WebPluginGeometryVector; + typedef std::vector WebPluginGeometryVector; WebPluginGeometryVector plugin_window_moves_; // A custom background for the widget. diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc index ae5984b..5cae2a9 100644 --- a/chrome/renderer/renderer_glue.cc +++ b/chrome/renderer/renderer_glue.cc @@ -205,8 +205,7 @@ bool ClipboardReadFilenames(Clipboard::Buffer buffer, return result; } -void GetPlugins(bool refresh, - std::vector* plugins) { +void GetPlugins(bool refresh, std::vector* plugins) { if (!RenderThread::current()->plugin_refresh_allowed()) refresh = false; RenderThread::current()->Send(new ViewHostMsg_GetPlugins(refresh, plugins)); diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index 68a14ad..1d2be20 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -55,26 +55,26 @@ #include "third_party/npapi/bindings/npapi_extensions_private.h" #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/plugin_host.h" +#include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/webcursor.h" #include "webkit/glue/webkit_glue.h" -#include "webkit/plugins/npapi/plugin_constants_win.h" -#include "webkit/plugins/npapi/plugin_instance.h" -#include "webkit/plugins/npapi/plugin_lib.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/npapi/plugin_host.h" -#include "webkit/plugins/npapi/plugin_stream_url.h" #if defined(ENABLE_GPU) -#include "webkit/plugins/npapi/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_constants_win.h" #endif #if defined(ENABLE_GPU) using gpu::Buffer; #endif -using webkit::npapi::WebPlugin; -using webkit::npapi::WebPluginDelegate; -using webkit::npapi::WebPluginResourceClient; +using webkit_glue::WebPlugin; +using webkit_glue::WebPluginDelegate; +using webkit_glue::WebPluginResourceClient; using WebKit::WebCursorInfo; using WebKit::WebKeyboardEvent; using WebKit::WebInputEvent; @@ -114,8 +114,8 @@ WebPluginDelegatePepper* WebPluginDelegatePepper::Create( const FilePath& filename, const std::string& mime_type, const base::WeakPtr& render_view) { - scoped_refptr plugin_lib( - webkit::npapi::PluginLib::CreatePluginLib(filename)); + scoped_refptr plugin_lib( + NPAPI::PluginLib::CreatePluginLib(filename)); if (plugin_lib.get() == NULL) return NULL; @@ -123,7 +123,7 @@ WebPluginDelegatePepper* WebPluginDelegatePepper::Create( if (err != NPERR_NO_ERROR) return NULL; - scoped_refptr instance( + scoped_refptr instance( plugin_lib->CreateInstance(mime_type)); return new WebPluginDelegatePepper(render_view, instance.get()); @@ -544,7 +544,7 @@ string16 WebPluginDelegatePepper::GetSelectedText(bool html) const { return string16(); string16 rv = UTF8ToUTF16(static_cast(text)); - webkit::npapi::PluginHost::Singleton()->host_functions()->memfree(text); + NPAPI::PluginHost::Singleton()->host_functions()->memfree(text); return rv; } @@ -680,8 +680,8 @@ NPError WebPluginDelegatePepper::Device3DInitializeContext( // Create an instance of the GPU plugin that is responsible for 3D // rendering. - nested_delegate_ = new WebPluginDelegateProxy( - "application/vnd.google.chrome.gpu-plugin", render_view_); + nested_delegate_ = new WebPluginDelegateProxy(kGPUPluginMimeType, + render_view_); // TODO(apatrick): should the GPU plugin be attached to plugin_? if (nested_delegate_->Initialize(GURL(), @@ -1270,8 +1270,7 @@ bool WebPluginDelegatePepper::VectorPrintPage(int page_number, size_in_pixels.height(), true, false, true, true); #endif // defined(OS_WIN) - webkit::npapi::PluginHost::Singleton()->host_functions()->memfree( - pdf_output); + NPAPI::PluginHost::Singleton()->host_functions()->memfree(pdf_output); return ret; } @@ -1379,7 +1378,7 @@ void WebPluginDelegatePepper::PrintEnd() { WebPluginDelegatePepper::WebPluginDelegatePepper( const base::WeakPtr& render_view, - webkit::npapi::PluginInstance *instance) + NPAPI::PluginInstance *instance) : render_view_(render_view), plugin_(NULL), instance_(instance), @@ -1637,7 +1636,7 @@ void WebPluginDelegatePepper::SendNestedDelegateGeometryToBrowser( return; } - webkit::npapi::WebPluginGeometry geom; + webkit_glue::WebPluginGeometry geom; geom.window = nested_delegate_->GetPluginWindowHandle(); geom.window_rect = window_rect; geom.clip_rect = clip_rect; diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index 6285424..cfe34a1 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -22,21 +22,19 @@ #include "third_party/npapi/bindings/npapi.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileChooserCompletion.h" -#include "webkit/plugins/npapi/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugin_delegate.h" class FilePath; class RenderView; class WebCursor; class WebPluginDelegateProxy; -namespace webkit { -namespace npapi { +namespace NPAPI { class PluginInstance; } -} // An implementation of WebPluginDelegate for Pepper in-process plugins. -class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, +class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate, public WebKit::WebFileChooserCompletion { public: static WebPluginDelegatePepper* Create( @@ -44,7 +42,7 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, const std::string& mime_type, const base::WeakPtr& render_view); - webkit::npapi::PluginInstance* instance() { return instance_.get(); } + NPAPI::PluginInstance* instance() { return instance_.get(); } // WebKit::WebFileChooserCompletion implementation. virtual void didChooseFile( @@ -54,7 +52,7 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, virtual bool Initialize(const GURL& url, const std::vector& arg_names, const std::vector& arg_values, - webkit::npapi::WebPlugin* plugin, + webkit_glue::WebPlugin* plugin, bool load_manually); virtual void PluginDestroyed(); virtual void UpdateGeometry(const gfx::Rect& window_rect, @@ -81,9 +79,9 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, virtual void DidFinishManualLoading(); virtual void DidManualLoadFail(); virtual void InstallMissingPlugin(); - virtual webkit::npapi::WebPluginResourceClient* CreateResourceClient( + virtual webkit_glue::WebPluginResourceClient* CreateResourceClient( unsigned long resource_id, const GURL& url, int notify_id); - virtual webkit::npapi::WebPluginResourceClient* CreateSeekableResourceClient( + virtual webkit_glue::WebPluginResourceClient* CreateSeekableResourceClient( unsigned long resource_id, int range_request_id); virtual bool StartFind(const string16& search_text, bool case_sensitive, @@ -210,7 +208,7 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, private: WebPluginDelegatePepper( const base::WeakPtr& render_view, - webkit::npapi::PluginInstance *instance); + NPAPI::PluginInstance *instance); ~WebPluginDelegatePepper(); // Set a task that calls the repaint callback the next time the window @@ -277,8 +275,8 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, base::WeakPtr render_view_; - webkit::npapi::WebPlugin* plugin_; - scoped_refptr instance_; + webkit_glue::WebPlugin* plugin_; + scoped_refptr instance_; NPWindow window_; gfx::Rect window_rect_; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 1b2e7d7..5c8d550 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -48,7 +48,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebString.h" #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" -#include "webkit/plugins/npapi/webplugin.h" +#include "webkit/glue/plugins/webplugin.h" #include "webkit/glue/webkit_glue.h" #if defined(OS_POSIX) @@ -65,7 +65,7 @@ using WebKit::WebView; // Proxy for WebPluginResourceClient. The object owns itself after creation, // deleting itself after its callback has been called. -class ResourceClientProxy : public webkit::npapi::WebPluginResourceClient { +class ResourceClientProxy : public webkit_glue::WebPluginResourceClient { public: ResourceClientProxy(PluginChannelHost* channel, int instance_id) : channel_(channel), instance_id_(instance_id), resource_id_(0), @@ -267,11 +267,10 @@ static bool SilverlightColorIsTransparent(const std::string& color) { return false; } -bool WebPluginDelegateProxy::Initialize( - const GURL& url, +bool WebPluginDelegateProxy::Initialize(const GURL& url, const std::vector& arg_names, const std::vector& arg_values, - webkit::npapi::WebPlugin* plugin, + webkit_glue::WebPlugin* plugin, bool load_manually) { IPC::ChannelHandle channel_handle; if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( @@ -1350,7 +1349,7 @@ void WebPluginDelegateProxy::OnHandleURLRequest( params.popups_allowed, params.notify_redirects); } -webkit::npapi::WebPluginResourceClient* +webkit_glue::WebPluginResourceClient* WebPluginDelegateProxy::CreateResourceClient( unsigned long resource_id, const GURL& url, int notify_id) { if (!channel_host_) @@ -1362,7 +1361,7 @@ WebPluginDelegateProxy::CreateResourceClient( return proxy; } -webkit::npapi::WebPluginResourceClient* +webkit_glue::WebPluginResourceClient* WebPluginDelegateProxy::CreateSeekableResourceClient( unsigned long resource_id, int range_request_id) { if (!channel_host_) @@ -1405,7 +1404,7 @@ bool WebPluginDelegateProxy::BindFakePluginWindowHandle(bool opaque) { // Since this isn't a real window, it doesn't get initial size and location // information the way a real windowed plugin would, so we need to feed it its // starting geometry. - webkit::npapi::WebPluginGeometry geom; + webkit_glue::WebPluginGeometry geom; geom.window = fake_window; geom.window_rect = plugin_rect_; geom.clip_rect = clip_rect_; @@ -1544,7 +1543,7 @@ bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() { // The move networks plugin needs to be informed of geometry updates // synchronously. - std::vector::iterator index; + std::vector::iterator index; for (index = info_.mime_types.begin(); index != info_.mime_types.end(); index++) { if (index->mime_type == "application/x-vnd.moveplayer.qm" || diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 30e212e..2c20583 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -18,8 +18,8 @@ #include "googleurl/src/gurl.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_message.h" -#include "webkit/plugins/npapi/webplugininfo.h" -#include "webkit/plugins/npapi/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugininfo.h" +#include "webkit/glue/plugins/webplugin_delegate.h" #if defined(OS_MACOSX) #include "base/hash_tables.h" @@ -44,16 +44,14 @@ namespace skia { class PlatformCanvas; } -namespace webkit { -namespace npapi { +namespace webkit_glue { class WebPlugin; } -} // An implementation of WebPluginDelegate that proxies all calls to // the plugin process. class WebPluginDelegateProxy - : public webkit::npapi::WebPluginDelegate, + : public webkit_glue::WebPluginDelegate, public IPC::Channel::Listener, public IPC::Message::Sender, public base::SupportsWeakPtr { @@ -66,7 +64,7 @@ class WebPluginDelegateProxy virtual bool Initialize(const GURL& url, const std::vector& arg_names, const std::vector& arg_values, - webkit::npapi::WebPlugin* plugin, + webkit_glue::WebPlugin* plugin, bool load_manually); virtual void UpdateGeometry(const gfx::Rect& window_rect, const gfx::Rect& clip_rect); @@ -115,9 +113,9 @@ class WebPluginDelegateProxy virtual void DidFinishManualLoading(); virtual void DidManualLoadFail(); virtual void InstallMissingPlugin(); - virtual webkit::npapi::WebPluginResourceClient* CreateResourceClient( + virtual webkit_glue::WebPluginResourceClient* CreateResourceClient( unsigned long resource_id, const GURL& url, int notify_id); - virtual webkit::npapi::WebPluginResourceClient* CreateSeekableResourceClient( + virtual webkit_glue::WebPluginResourceClient* CreateSeekableResourceClient( unsigned long resource_id, int range_request_id); CommandBufferProxy* CreateCommandBuffer(); @@ -233,13 +231,13 @@ class WebPluginDelegateProxy #endif base::WeakPtr render_view_; - webkit::npapi::WebPlugin* plugin_; + webkit_glue::WebPlugin* plugin_; bool uses_shared_bitmaps_; gfx::PluginWindowHandle window_; scoped_refptr channel_host_; std::string mime_type_; int instance_id_; - webkit::npapi::WebPluginInfo info_; + WebPluginInfo info_; gfx::Rect plugin_rect_; gfx::Rect clip_rect_; diff --git a/chrome/test/plugin/plugin_test.cpp b/chrome/test/plugin/plugin_test.cpp index ed052a0..c68dd99 100644 --- a/chrome/test/plugin/plugin_test.cpp +++ b/chrome/test/plugin/plugin_test.cpp @@ -48,9 +48,8 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_status.h" #include "third_party/npapi/bindings/npapi.h" -#include "webkit/plugins/npapi/plugin_constants_win.h" -#include "webkit/plugins/npapi/plugin_list.h" -#include "webkit/plugins/plugin_switches.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_list.h" #if defined(OS_WIN) #include "base/win/registry.h" @@ -91,7 +90,7 @@ class PluginTest : public UITest { } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) { // When testing the old WMP plugin, we need to force Chrome to not load // the new plugin. - launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin); + launch_arguments_.AppendSwitch(kUseOldWMPPluginSwitch); } else if (strcmp(test_info->name(), "FlashSecurity") == 0) { launch_arguments_.AppendSwitchASCII(switches::kTestSandbox, "security_tests.dll"); diff --git a/webkit/glue/plugins/DEPS b/webkit/glue/plugins/DEPS new file mode 100644 index 0000000..024a4ef --- /dev/null +++ b/webkit/glue/plugins/DEPS @@ -0,0 +1,9 @@ +include_rules = [ + "+ppapi", + + # Files in this directory must not depend on the proxy, because the proxy + # depends on IPC which we don't want to have in /webkit. + "-ppapi/proxy", + + "+printing", +] diff --git a/webkit/glue/plugins/carbon_plugin_window_tracker_mac.cc b/webkit/glue/plugins/carbon_plugin_window_tracker_mac.cc new file mode 100644 index 0000000..c4ae72d --- /dev/null +++ b/webkit/glue/plugins/carbon_plugin_window_tracker_mac.cc @@ -0,0 +1,55 @@ +// 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 "base/logging.h" +#include "webkit/glue/plugins/carbon_plugin_window_tracker_mac.h" + +CarbonPluginWindowTracker::CarbonPluginWindowTracker() { +} + +CarbonPluginWindowTracker* CarbonPluginWindowTracker::SharedInstance() { + static CarbonPluginWindowTracker* tracker = new CarbonPluginWindowTracker(); + return tracker; +} + +WindowRef CarbonPluginWindowTracker::CreateDummyWindowForDelegate( + OpaquePluginRef delegate) { + // The real size will be set by the plugin instance, once that size is known. + Rect window_bounds = { 0, 0, 100, 100 }; + WindowRef new_ref = NULL; + if (CreateNewWindow(kDocumentWindowClass, + kWindowNoTitleBarAttribute, + &window_bounds, + &new_ref) == noErr) { + window_to_delegate_map_[new_ref] = delegate; + delegate_to_window_map_[delegate] = new_ref; + } + return new_ref; +} + +OpaquePluginRef CarbonPluginWindowTracker::GetDelegateForDummyWindow( + WindowRef window) const { + WindowToDelegateMap::const_iterator i = window_to_delegate_map_.find(window); + if (i != window_to_delegate_map_.end()) + return i->second; + return NULL; +} + +WindowRef CarbonPluginWindowTracker::GetDummyWindowForDelegate( + OpaquePluginRef delegate) const { + DelegateToWindowMap::const_iterator i = + delegate_to_window_map_.find(delegate); + if (i != delegate_to_window_map_.end()) + return i->second; + return NULL; +} + +void CarbonPluginWindowTracker::DestroyDummyWindowForDelegate( + OpaquePluginRef delegate, WindowRef window) { + DCHECK(GetDelegateForDummyWindow(window) == delegate); + window_to_delegate_map_.erase(window); + delegate_to_window_map_.erase(delegate); + if (window) // Check just in case the initial window creation failed. + DisposeWindow(window); +} diff --git a/webkit/glue/plugins/carbon_plugin_window_tracker_mac.h b/webkit/glue/plugins/carbon_plugin_window_tracker_mac.h new file mode 100644 index 0000000..90fc318 --- /dev/null +++ b/webkit/glue/plugins/carbon_plugin_window_tracker_mac.h @@ -0,0 +1,53 @@ +// 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 WEBKIT_GLUE_PLUGINS_CARBON_PLUGIN_WINDOW_TRACKER_MAC_H_ +#define WEBKIT_GLUE_PLUGINS_CARBON_PLUGIN_WINDOW_TRACKER_MAC_H_ + +#include +#include + +#include "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; + +// Creates and tracks the invisible windows that are necessary for +// Carbon-event-model plugins. +// +// Serves as a bridge between plugin delegate instances and the Carbon +// interposing library. The Carbon functions we interpose work in terms of +// WindowRefs, and we need to be able to map from those back to the plugin +// delegates that know what we should claim about the state of the window. +class __attribute__((visibility("default"))) CarbonPluginWindowTracker { + public: + CarbonPluginWindowTracker(); + + // Returns the shared window tracker instance. + static CarbonPluginWindowTracker* SharedInstance(); + + // Creates a new carbon window associated with |delegate|. + WindowRef CreateDummyWindowForDelegate(OpaquePluginRef delegate); + + // Returns the WebPluginDelegate associated with the given dummy window. + OpaquePluginRef GetDelegateForDummyWindow(WindowRef window) const; + + // Returns the dummy window associated with |delegate|. + WindowRef GetDummyWindowForDelegate(OpaquePluginRef delegate) const; + + // Destroys the dummy window for |delegate|. + void DestroyDummyWindowForDelegate(OpaquePluginRef delegate, + WindowRef window); + + private: + typedef std::map WindowToDelegateMap; + typedef std::map DelegateToWindowMap; + WindowToDelegateMap window_to_delegate_map_; + DelegateToWindowMap delegate_to_window_map_; + + DISALLOW_COPY_AND_ASSIGN(CarbonPluginWindowTracker); +}; + +#endif // WEBKIT_GLUE_PLUGINS_CARBON_PLUGIN_WINDOW_TRACKER_MAC_H_ diff --git a/webkit/glue/plugins/coregraphics_private_symbols_mac.h b/webkit/glue/plugins/coregraphics_private_symbols_mac.h new file mode 100644 index 0000000..0342d6f --- /dev/null +++ b/webkit/glue/plugins/coregraphics_private_symbols_mac.h @@ -0,0 +1,27 @@ +// 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 WEBKIT_GLUE_PLUGINS_COREGRAPHICS_PRIVATE_SYMBOLS_MAC_H_ +#define WEBKIT_GLUE_PLUGINS_COREGRAPHICS_PRIVATE_SYMBOLS_MAC_H_ + +// These are CoreGraphics SPI, verified to exist in both 10.5 and 10.6. + +#ifdef __cplusplus +extern "C" { +#endif + +// Copies the contents of the window with id |wid| into the given rect in the +// given context +OSStatus CGContextCopyWindowCaptureContentsToRect( + CGContextRef, CGRect, int cid, int wid, int unknown); + +// Returns the connection ID we need for the third argument to +// CGContextCopyWindowCaptureContentsToRect +int _CGSDefaultConnection(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBKIT_GLUE_PLUGINS_COREGRAPHICS_PRIVATE_SYMBOLS_MAC_H_ diff --git a/webkit/glue/plugins/default_plugin_shared.h b/webkit/glue/plugins/default_plugin_shared.h new file mode 100644 index 0000000..79d06b3 --- /dev/null +++ b/webkit/glue/plugins/default_plugin_shared.h @@ -0,0 +1,31 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Thes file contains stuff that should be shared among projects that do some +// special handling with default plugin + +#ifndef WEBKIT_GLUE_PLUGINS_DEFAULT_PLUGIN_SHARED_H +#define WEBKIT_GLUE_PLUGINS_DEFAULT_PLUGIN_SHARED_H + +namespace default_plugin { + +// We use the NPNGetValue host function to send notification message to host. +// This corresponds to NPNVariable defined in npapi.h, and should be chosen so +// as to not overlap values if NPAPI is updated. + +const int kMissingPluginStatusStart = 5000; + +enum MissingPluginStatus { + MISSING_PLUGIN_AVAILABLE, + MISSING_PLUGIN_USER_STARTED_DOWNLOAD +}; + +#if defined(OS_WIN) +#include +const int kInstallMissingPluginMessage = WM_APP + 117; +#endif + +} // namespace default_plugin + +#endif // WEBKIT_GLUE_PLUGINS_DEFAULT_PLUGIN_SHARED_H diff --git a/webkit/glue/plugins/gtk_plugin_container.cc b/webkit/glue/plugins/gtk_plugin_container.cc new file mode 100644 index 0000000..c80bbf1 --- /dev/null +++ b/webkit/glue/plugins/gtk_plugin_container.cc @@ -0,0 +1,85 @@ +// 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 "webkit/glue/plugins/gtk_plugin_container.h" + +#include + +#include "base/basictypes.h" + +namespace { + +// NOTE: This class doesn't have constructors/destructors, it is created +// through GLib's object management. +class GtkPluginContainer : public GtkSocket { + public: + // Sets the requested size of the widget. + void set_size(int width, int height) { + width_ = width; + height_ = height; + } + + // Casts a widget into a GtkPluginContainer, after checking the type. + template + static GtkPluginContainer *CastChecked(T *instance) { + return G_TYPE_CHECK_INSTANCE_CAST(instance, GetType(), GtkPluginContainer); + } + + // Create and register our custom container type with GTK. + static GType GetType() { + static GType type = 0; // We only want to register our type once. + if (!type) { + static const GTypeInfo info = { + sizeof(GtkSocketClass), + NULL, NULL, + static_cast(&ClassInit), + NULL, NULL, + sizeof(GtkPluginContainer), + 0, &InstanceInit, + }; + type = g_type_register_static(GTK_TYPE_SOCKET, + "GtkPluginContainer", + &info, + static_cast(0)); + } + return type; + } + + // Implementation of the class initializer. + static void ClassInit(gpointer klass, gpointer class_data_unusued) { + GtkWidgetClass* widget_class = reinterpret_cast(klass); + widget_class->size_request = &HandleSizeRequest; + } + + // Implementation of the instance initializer (constructor). + static void InstanceInit(GTypeInstance *instance, gpointer klass) { + GtkPluginContainer *container = CastChecked(instance); + container->set_size(0, 0); + } + + // Report our allocation size during size requisition. + static void HandleSizeRequest(GtkWidget* widget, + GtkRequisition* requisition) { + GtkPluginContainer *container = CastChecked(widget); + requisition->width = container->width_; + requisition->height = container->height_; + } + + int width_; + int height_; + DISALLOW_IMPLICIT_CONSTRUCTORS(GtkPluginContainer); +}; + +} // anonymous namespace + +// Create a new instance of our GTK widget object. +GtkWidget* gtk_plugin_container_new() { + return GTK_WIDGET(g_object_new(GtkPluginContainer::GetType(), NULL)); +} + +void gtk_plugin_container_set_size(GtkWidget *widget, int width, int height) { + GtkPluginContainer::CastChecked(widget)->set_size(width, height); + // Signal the parent that the size request has changed. + gtk_widget_queue_resize_no_redraw(widget); +} diff --git a/webkit/glue/plugins/gtk_plugin_container.h b/webkit/glue/plugins/gtk_plugin_container.h new file mode 100644 index 0000000..eed6b94 --- /dev/null +++ b/webkit/glue/plugins/gtk_plugin_container.h @@ -0,0 +1,26 @@ +// 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 WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_H_ +#define WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_H_ + +// Windowed plugins are embedded via XEmbed, which is implemented by +// GtkPlug/GtkSocket. But we want to control sizing and positioning +// directly, so we need a subclass of GtkSocket that sidesteps the +// size_request handler. +// +// The custom size_request handler just reports the size set by +// gtk_plugin_container_set_size. + +typedef struct _GtkWidget GtkWidget; + +// Return a new GtkPluginContainer. +// Intentionally GTK-style here since we're creating a custom GTK widget. +// This is a GtkSocket subclass; see its documentation for available methods. +GtkWidget* gtk_plugin_container_new(); + +// Sets the size of the GtkPluginContainer. +void gtk_plugin_container_set_size(GtkWidget *widget, int width, int height); + +#endif // WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_H_ diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.cc b/webkit/glue/plugins/gtk_plugin_container_manager.cc new file mode 100644 index 0000000..2f82b24 --- /dev/null +++ b/webkit/glue/plugins/gtk_plugin_container_manager.cc @@ -0,0 +1,155 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/gtk_plugin_container_manager.h" + +#include + +#include "base/logging.h" +#include "gfx/gtk_util.h" +#include "webkit/glue/plugins/gtk_plugin_container.h" +#include "webkit/glue/plugins/webplugin.h" + +GtkPluginContainerManager::GtkPluginContainerManager() : host_widget_(NULL) {} + +GtkPluginContainerManager::~GtkPluginContainerManager() {} + +GtkWidget* GtkPluginContainerManager::CreatePluginContainer( + gfx::PluginWindowHandle id) { + DCHECK(host_widget_); + GtkWidget *widget = gtk_plugin_container_new(); + plugin_window_to_widget_map_.insert(std::make_pair(id, widget)); + + // The Realize callback is responsible for adding the plug into the socket. + // The reason is 2-fold: + // - the plug can't be added until the socket is realized, but this may not + // happen until the socket is attached to a top-level window, which isn't the + // case for background tabs. + // - when dragging tabs, the socket gets unrealized, which breaks the XEMBED + // connection. We need to make it again when the tab is reattached, and the + // socket gets realized again. + // + // Note, the RealizeCallback relies on the plugin_window_to_widget_map_ to + // have the mapping. + g_signal_connect(widget, "realize", + G_CALLBACK(RealizeCallback), this); + + // Don't destroy the widget when the plug is removed. + g_signal_connect(widget, "plug-removed", + G_CALLBACK(gtk_true), NULL); + + gtk_container_add(GTK_CONTAINER(host_widget_), widget); + gtk_widget_show(widget); + + return widget; +} + +void GtkPluginContainerManager::DestroyPluginContainer( + gfx::PluginWindowHandle id) { + DCHECK(host_widget_); + GtkWidget* widget = MapIDToWidget(id); + if (widget) + gtk_widget_destroy(widget); + + plugin_window_to_widget_map_.erase(id); +} + +void GtkPluginContainerManager::MovePluginContainer( + const webkit_glue::WebPluginGeometry& move) { + DCHECK(host_widget_); + GtkWidget *widget = MapIDToWidget(move.window); + if (!widget) + return; + + DCHECK(!GTK_WIDGET_NO_WINDOW(widget)); + + if (!move.visible) { + gtk_widget_hide(widget); + return; + } + + gtk_widget_show(widget); + + if (!move.rects_valid) + return; + + // TODO(piman): if the widget hasn't been realized (e.g. the tab has been + // torn off and the parent gtk widget has been detached from the hierarchy), + // we lose the cutout information. + if (GTK_WIDGET_REALIZED(widget)) { + GdkRectangle clip_rect = move.clip_rect.ToGdkRectangle(); + GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); + gfx::SubtractRectanglesFromRegion(clip_region, move.cutout_rects); + gdk_window_shape_combine_region(widget->window, clip_region, 0, 0); + gdk_region_destroy(clip_region); + } + + // Update the window position. Resizing is handled by WebPluginDelegate. + // TODO(deanm): Verify that we only need to move and not resize. + // TODO(evanm): we should cache the last shape and position and skip all + // of this business in the common case where nothing has changed. + int current_x, current_y; + + // Until the above TODO is resolved, we can grab the last position + // off of the GtkFixed with a bit of hackery. + GValue value = {0}; + g_value_init(&value, G_TYPE_INT); + gtk_container_child_get_property(GTK_CONTAINER(host_widget_), widget, + "x", &value); + current_x = g_value_get_int(&value); + gtk_container_child_get_property(GTK_CONTAINER(host_widget_), widget, + "y", &value); + current_y = g_value_get_int(&value); + g_value_unset(&value); + + if (move.window_rect.x() != current_x || + move.window_rect.y() != current_y) { + // Calling gtk_fixed_move unnecessarily is a no-no, as it causes the + // parent window to repaint! + gtk_fixed_move(GTK_FIXED(host_widget_), + widget, + move.window_rect.x(), + move.window_rect.y()); + } + + gtk_plugin_container_set_size(widget, + move.window_rect.width(), + move.window_rect.height()); +} + +GtkWidget* GtkPluginContainerManager::MapIDToWidget( + gfx::PluginWindowHandle id) { + PluginWindowToWidgetMap::const_iterator i = + plugin_window_to_widget_map_.find(id); + if (i != plugin_window_to_widget_map_.end()) + return i->second; + + LOG(ERROR) << "Request for widget host for unknown window id " << id; + + return NULL; +} + +gfx::PluginWindowHandle GtkPluginContainerManager::MapWidgetToID( + GtkWidget* widget) { + for (PluginWindowToWidgetMap::const_iterator i = + plugin_window_to_widget_map_.begin(); + i != plugin_window_to_widget_map_.end(); ++i) { + if (i->second == widget) + return i->first; + } + + LOG(ERROR) << "Request for id for unknown widget"; + return 0; +} + +// static +void GtkPluginContainerManager::RealizeCallback(GtkWidget* widget, + void* user_data) { + GtkPluginContainerManager* plugin_container_manager = + static_cast(user_data); + + gfx::PluginWindowHandle id = plugin_container_manager->MapWidgetToID(widget); + if (id) + gtk_socket_add_id(GTK_SOCKET(widget), id); +} diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.h b/webkit/glue/plugins/gtk_plugin_container_manager.h new file mode 100644 index 0000000..7f7db8d --- /dev/null +++ b/webkit/glue/plugins/gtk_plugin_container_manager.h @@ -0,0 +1,57 @@ +// 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 WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_MANAGER_H_ +#define WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_MANAGER_H_ + +#include +#include + +#include "gfx/native_widget_types.h" + +typedef struct _GtkWidget GtkWidget; + +namespace webkit_glue { +struct WebPluginGeometry; +} + +// Helper class that creates and manages plugin containers (GtkSocket). +class GtkPluginContainerManager { + public: + GtkPluginContainerManager(); + ~GtkPluginContainerManager(); + + // Sets the widget that will host the plugin containers. Must be a GtkFixed. + void set_host_widget(GtkWidget *widget) { host_widget_ = widget; } + + // Creates a new plugin container, for a given plugin XID. + GtkWidget* CreatePluginContainer(gfx::PluginWindowHandle id); + + // Destroys a plugin container, given the plugin XID. + void DestroyPluginContainer(gfx::PluginWindowHandle id); + + // Takes an update from WebKit about a plugin's position and side and moves + // the plugin accordingly. + void MovePluginContainer(const webkit_glue::WebPluginGeometry& move); + + private: + // Maps a plugin XID to the corresponding container widget. + GtkWidget* MapIDToWidget(gfx::PluginWindowHandle id); + + // Maps a container widget to the corresponding plugin XID. + gfx::PluginWindowHandle MapWidgetToID(GtkWidget* widget); + + // Callback for when the plugin container gets realized, at which point it + // plugs the plugin XID. + static void RealizeCallback(GtkWidget *widget, void *user_data); + + // Parent of the plugin containers. + GtkWidget* host_widget_; + + // A map that associates plugin containers to the plugin XID. + typedef std::map PluginWindowToWidgetMap; + PluginWindowToWidgetMap plugin_window_to_widget_map_; +}; + +#endif // WEBKIT_GLUE_PLUGINS_GTK_PLUGIN_CONTAINER_MANAGER_H_ diff --git a/webkit/glue/plugins/npapi_extension_thunk.cc b/webkit/glue/plugins/npapi_extension_thunk.cc new file mode 100644 index 0000000..05a9c5d --- /dev/null +++ b/webkit/glue/plugins/npapi_extension_thunk.cc @@ -0,0 +1,551 @@ +// 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 "webkit/glue/plugins/npapi_extension_thunk.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "third_party/npapi/bindings/npapi_extensions.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/webkit_glue.h" + +// FindInstance() +// Finds a PluginInstance from an NPP. +// The caller must take a reference if needed. +static NPAPI::PluginInstance* FindInstance(NPP id) { + if (id == NULL) { + NOTREACHED(); + return NULL; + } + return static_cast(id->ndata); +} + +// 2D device API --------------------------------------------------------------- + +static NPError Device2DQueryCapability(NPP id, int32_t capability, + int32_t* value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + plugin->webplugin()->delegate()->Device2DQueryCapability(capability, value); + return NPERR_NO_ERROR; + } else { + return NPERR_GENERIC_ERROR; + } +} + +static NPError Device2DQueryConfig(NPP id, + const NPDeviceConfig* request, + NPDeviceConfig* obtain) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device2DQueryConfig( + static_cast(request), + static_cast(obtain)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DInitializeContext(NPP id, + const NPDeviceConfig* config, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device2DInitializeContext( + static_cast(config), + static_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DSetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device2DSetStateContext( + static_cast(context), state, value); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DGetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t* value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device2DGetStateContext( + static_cast(context), state, value); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DFlushContext(NPP id, + NPDeviceContext* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + NPError err = plugin->webplugin()->delegate()->Device2DFlushContext( + id, static_cast(context), callback, user_data); + + // Invoke the callback to inform the caller the work was done. + // TODO(brettw) this is probably not how we want this to work, this should + // happen when the frame is painted so the plugin knows when it can draw + // the next frame. + if (callback != NULL) + (*callback)(id, context, err, user_data); + + // Return any errors. + return err; + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DDestroyContext(NPP id, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device2DDestroyContext( + static_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DCreateBuffer(NPP id, + NPDeviceContext* context, + size_t size, + int32_t* buffer_id) { + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DDestroyBuffer(NPP id, + NPDeviceContext* context, + int32_t buffer_id) { + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DMapBuffer(NPP id, + NPDeviceContext* context, + int32_t buffer_id, + NPDeviceBuffer* buffer) { + return NPERR_GENERIC_ERROR; +} + +// 3D device API --------------------------------------------------------------- + +static NPError Device3DQueryCapability(NPP id, int32_t capability, + int32_t* value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + plugin->webplugin()->delegate()->Device3DQueryCapability(capability, value); + return NPERR_NO_ERROR; + } else { + return NPERR_GENERIC_ERROR; + } +} + +static NPError Device3DQueryConfig(NPP id, + const NPDeviceConfig* request, + NPDeviceConfig* obtain) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DQueryConfig( + static_cast(request), + static_cast(obtain)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DInitializeContext(NPP id, + const NPDeviceConfig* config, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DInitializeContext( + static_cast(config), + static_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DSetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DSetStateContext( + static_cast(context), state, value); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DGetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t* value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DGetStateContext( + static_cast(context), state, value); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DFlushContext(NPP id, + NPDeviceContext* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DFlushContext( + id, static_cast(context), callback, user_data); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DDestroyContext(NPP id, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DDestroyContext( + static_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DCreateBuffer(NPP id, + NPDeviceContext* context, + size_t size, + int32_t* buffer_id) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DCreateBuffer( + static_cast(context), size, buffer_id); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DDestroyBuffer(NPP id, + NPDeviceContext* context, + int32_t buffer_id) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DDestroyBuffer( + static_cast(context), buffer_id); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DMapBuffer(NPP id, + NPDeviceContext* context, + int32_t buffer_id, + NPDeviceBuffer* buffer) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DMapBuffer( + static_cast(context), buffer_id, buffer); + } + return NPERR_GENERIC_ERROR; +} + +// Experimental 3D device API -------------------------------------------------- + +static NPError Device3DGetNumConfigs(NPP id, int32_t* num_configs) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DGetNumConfigs(num_configs); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DGetConfigAttribs(NPP id, + int32_t config, + int32_t* attrib_list) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DGetConfigAttribs( + config, + attrib_list); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DCreateContext(NPP id, + int32_t config, + const int32_t* attrib_list, + NPDeviceContext** context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DCreateContext( + config, + attrib_list, + reinterpret_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DSynchronizeContext( + NPP id, + NPDeviceContext* context, + NPDeviceSynchronizationMode mode, + const int32_t* input_attrib_list, + int32_t* output_attrib_list, + NPDeviceSynchronizeContextCallbackPtr callback, + void* callback_data) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DSynchronizeContext( + id, + static_cast(context), + mode, + input_attrib_list, + output_attrib_list, + callback, + callback_data); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DRegisterCallback( + NPP id, + NPDeviceContext* context, + int32_t callback_type, + NPDeviceGenericCallbackPtr callback, + void* callback_data) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DRegisterCallback( + id, + static_cast(context), + callback_type, + callback, + callback_data); + } + return NPERR_GENERIC_ERROR; +} + +// Audio device API ------------------------------------------------------------ + +static NPError DeviceAudioQueryCapability(NPP id, int32_t capability, + int32_t* value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + plugin->webplugin()->delegate()->DeviceAudioQueryCapability(capability, + value); + return NPERR_NO_ERROR; + } else { + return NPERR_GENERIC_ERROR; + } +} + +static NPError DeviceAudioQueryConfig(NPP id, + const NPDeviceConfig* request, + NPDeviceConfig* obtain) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->DeviceAudioQueryConfig( + static_cast(request), + static_cast(obtain)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError DeviceAudioInitializeContext(NPP id, + const NPDeviceConfig* config, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->DeviceAudioInitializeContext( + static_cast(config), + static_cast(context)); + } + return NPERR_GENERIC_ERROR; +} + +static NPError DeviceAudioSetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t value) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + return plugin->webplugin()->delegate()->DeviceAudioSetStateContext( + static_cast(context), state, value); + } + return NPERR_GENERIC_ERROR; +} + +static NPError DeviceAudioGetStateContext(NPP id, + NPDeviceContext* context, + int32_t state, + intptr_t* value) { + scoped_refptr plugin(FindInstance(id)); + return plugin->webplugin()->delegate()->DeviceAudioGetStateContext( + static_cast(context), state, value); +} + +static NPError DeviceAudioFlushContext(NPP id, + NPDeviceContext* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + scoped_refptr plugin(FindInstance(id)); + return plugin->webplugin()->delegate()->DeviceAudioFlushContext( + id, static_cast(context), callback, user_data); +} + +static NPError DeviceAudioDestroyContext(NPP id, + NPDeviceContext* context) { + scoped_refptr plugin(FindInstance(id)); + return plugin->webplugin()->delegate()->DeviceAudioDestroyContext( + static_cast(context)); +} +// ----------------------------------------------------------------------------- + +static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) { + static NPDevice device_2d = { + Device2DQueryCapability, + Device2DQueryConfig, + Device2DInitializeContext, + Device2DSetStateContext, + Device2DGetStateContext, + Device2DFlushContext, + Device2DDestroyContext, + Device2DCreateBuffer, + Device2DDestroyBuffer, + Device2DMapBuffer, + NULL, + NULL, + NULL, + NULL, + NULL, + }; + static NPDevice device_3d = { + Device3DQueryCapability, + Device3DQueryConfig, + Device3DInitializeContext, + Device3DSetStateContext, + Device3DGetStateContext, + Device3DFlushContext, + Device3DDestroyContext, + Device3DCreateBuffer, + Device3DDestroyBuffer, + Device3DMapBuffer, + Device3DGetNumConfigs, + Device3DGetConfigAttribs, + Device3DCreateContext, + Device3DRegisterCallback, + Device3DSynchronizeContext, + }; + static NPDevice device_audio = { + DeviceAudioQueryCapability, + DeviceAudioQueryConfig, + DeviceAudioInitializeContext, + DeviceAudioSetStateContext, + DeviceAudioGetStateContext, + DeviceAudioFlushContext, + DeviceAudioDestroyContext, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + }; + + switch (device_id) { + case NPPepper2DDevice: + return const_cast(&device_2d); + case NPPepper3DDevice: + return const_cast(&device_3d); + case NPPepperAudioDevice: + return const_cast(&device_audio); + default: + return NULL; + } +} + +static NPError ChooseFile(NPP id, + const char* mime_types, + NPChooseFileMode mode, + NPChooseFileCallback callback, + void* user_data) { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NPERR_GENERIC_ERROR; + + if (!plugin->webplugin()->delegate()->ChooseFile(mime_types, + static_cast(mode), + callback, user_data)) + return NPERR_GENERIC_ERROR; + + return NPERR_NO_ERROR; +} + +static void NumberOfFindResultsChanged(NPP id, int total, bool final_result) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) { + plugin->webplugin()->delegate()->NumberOfFindResultsChanged( + total, final_result); + } +} + +static void SelectedFindResultChanged(NPP id, int index) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) + plugin->webplugin()->delegate()->SelectedFindResultChanged(index); +} + +static NPWidgetExtensions* GetWidgetExtensions(NPP id) { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NULL; + + return plugin->webplugin()->delegate()->GetWidgetExtensions(); +} + +static NPError NPSetCursor(NPP id, NPCursorType type) { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NPERR_GENERIC_ERROR; + + return plugin->webplugin()->delegate()->SetCursor(type) ? + NPERR_NO_ERROR : NPERR_GENERIC_ERROR; +} + +static NPFontExtensions* GetFontExtensions(NPP id) { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NULL; + + return plugin->webplugin()->delegate()->GetFontExtensions(); +} + +namespace NPAPI { + +NPError GetPepperExtensionsFunctions(void* value) { + static const NPNExtensions kExtensions = { + &AcquireDevice, + &NumberOfFindResultsChanged, + &SelectedFindResultChanged, + &ChooseFile, + &GetWidgetExtensions, + &NPSetCursor, + &GetFontExtensions, + }; + + // Return a pointer to the canonical function table. + NPNExtensions* extensions = const_cast(&kExtensions); + NPNExtensions** exts = reinterpret_cast(value); + *exts = extensions; + return NPERR_NO_ERROR; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/npapi_extension_thunk.h b/webkit/glue/plugins/npapi_extension_thunk.h new file mode 100644 index 0000000..fada6bc --- /dev/null +++ b/webkit/glue/plugins/npapi_extension_thunk.h @@ -0,0 +1,23 @@ +// 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 WEBKIT_GLUE_PLUGINS_NPAPI_EXTENSION_THUNK_H_ +#define WEBKIT_GLUE_PLUGINS_NPAPI_EXTENSION_THUNK_H_ + +#include "third_party/npapi/bindings/npapi_extensions.h" + +// This file implements forwarding for the NPAPI "Pepper" extensions through to +// the WebPluginDelegate associated with the plugin. + +namespace NPAPI { + +// Implements NPN_GetValue for the case of NPNVPepperExtensions. The function +// pointers in the returned structure implement all the extensions. +NPError GetPepperExtensionsFunctions(void* value); + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGINS_NPAPI_EXTENSION_THUNK_H_ + + diff --git a/webkit/glue/plugins/plugin_constants_win.h b/webkit/glue/plugins/plugin_constants_win.h new file mode 100644 index 0000000..9913e5d --- /dev/null +++ b/webkit/glue/plugins/plugin_constants_win.h @@ -0,0 +1,41 @@ +// Copyright (c) 2006-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 WEBKIT_GLUE_PLUGIN_CONSTANTS_WIN_H_ +#define WEBKIT_GLUE_PLUGIN_CONSTANTS_WIN_H_ + +// Used by the plugins_test when testing the older WMP plugin to force the new +// plugin to not get loaded. +#define kUseOldWMPPluginSwitch "use-old-wmp" + +// The window class name for a plugin window. +#define kNativeWindowClassName L"NativeWindowClass" + +// The name of the window class name for the wrapper HWND around the actual +// plugin window that's used when running in multi-process mode. This window +// is created on the browser UI thread. +#define kWrapperNativeWindowClassName L"WrapperNativeWindowClass" + +// The name of the custom window message that the browser uses to tell the +// plugin process to paint a window. +#define kPaintMessageName L"Chrome_CustomPaint" + +// The name of the registry key which NPAPI plugins update on installation. +#define kRegistryMozillaPlugins L"SOFTWARE\\MozillaPlugins" + +#define kMozillaActiveXPlugin L"npmozax.dll" +#define kNewWMPPlugin L"np-mswmp.dll" +#define kOldWMPPlugin L"npdsplay.dll" +#define kYahooApplicationStatePlugin L"npystate.dll" +#define kWanWangProtocolHandlerPlugin L"npww.dll" +#define kFlashPlugin L"npswf32.dll" +#define kAcrobatReaderPlugin L"nppdf32.dll" +#define kRealPlayerPlugin L"nppl3260.dll" +#define kSilverlightPlugin L"npctrl.dll" +#define kJavaPlugin1 L"npjp2.dll" +#define kJavaPlugin2 L"npdeploytk.dll" + +#define kGPUPluginMimeType "application/vnd.google.chrome.gpu-plugin" + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_LIST_H_ diff --git a/webkit/glue/plugins/plugin_group.cc b/webkit/glue/plugins/plugin_group.cc new file mode 100644 index 0000000..548e624 --- /dev/null +++ b/webkit/glue/plugins/plugin_group.cc @@ -0,0 +1,407 @@ +// 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 "webkit/glue/plugins/plugin_group.h" + +#include "base/linked_ptr.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "base/version.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugininfo.h" + +const char* PluginGroup::kAdobeReaderGroupName = "Adobe Reader"; + +/*static*/ +std::set* PluginGroup::policy_disabled_plugin_patterns_; + +/*static*/ +void PluginGroup::SetPolicyDisabledPluginPatterns( + const std::set& set) { + if (!policy_disabled_plugin_patterns_) + policy_disabled_plugin_patterns_ = new std::set(set); + else + *policy_disabled_plugin_patterns_ = set; +} + +/*static*/ +bool PluginGroup::IsPluginNameDisabledByPolicy(const string16& plugin_name) { + if (!policy_disabled_plugin_patterns_) + return false; + + std::set::const_iterator pattern( + policy_disabled_plugin_patterns_->begin()); + while (pattern != policy_disabled_plugin_patterns_->end()) { + if (MatchPattern(plugin_name, *pattern)) + return true; + ++pattern; + } + + return false; +} + +/*static*/ +bool PluginGroup::IsPluginPathDisabledByPolicy(const FilePath& plugin_path) { + std::vector plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); + for (std::vector::const_iterator it = plugins.begin(); + it != plugins.end(); + ++it) { + if (FilePath::CompareEqualIgnoreCase(it->path.value(), + plugin_path.value()) && IsPluginNameDisabledByPolicy(it->name)) { + return true; + } + } + return false; +} + +VersionRange::VersionRange(VersionRangeDefinition definition) + : low_str(definition.version_matcher_low), + high_str(definition.version_matcher_high), + min_str(definition.min_version) { + if (!low_str.empty()) + low.reset(Version::GetVersionFromString(low_str)); + if (!high_str.empty()) + high.reset(Version::GetVersionFromString(high_str)); + if (!min_str.empty()) + min.reset(Version::GetVersionFromString(min_str)); +} + +VersionRange::VersionRange(const VersionRange& other) { + InitFrom(other); +} + +VersionRange& VersionRange::operator=(const VersionRange& other) { + InitFrom(other); + return *this; +} + +VersionRange::~VersionRange() {} + +void VersionRange::InitFrom(const VersionRange& other) { + low_str = other.low_str; + high_str = other.high_str; + min_str = other.min_str; + low.reset(Version::GetVersionFromString(other.low_str)); + high.reset(Version::GetVersionFromString(other.high_str)); + min.reset(Version::GetVersionFromString(other.min_str)); +} + +PluginGroup::PluginGroup(const string16& group_name, + const string16& name_matcher, + const std::string& update_url, + const std::string& identifier) + : identifier_(identifier), + group_name_(group_name), + name_matcher_(name_matcher), + update_url_(update_url), + enabled_(false), + version_(Version::GetVersionFromString("0")) { +} + +void PluginGroup::InitFrom(const PluginGroup& other) { + identifier_ = other.identifier_; + group_name_ = other.group_name_; + name_matcher_ = other.name_matcher_; + description_ = other.description_; + update_url_ = other.update_url_; + enabled_ = other.enabled_; + for (size_t i = 0; i < other.version_ranges_.size(); ++i) + version_ranges_.push_back(other.version_ranges_[i]); + DCHECK_EQ(other.web_plugin_infos_.size(), other.web_plugin_positions_.size()); + for (size_t i = 0; i < other.web_plugin_infos_.size(); ++i) + AddPlugin(other.web_plugin_infos_[i], other.web_plugin_positions_[i]); + if (!version_.get()) + version_.reset(Version::GetVersionFromString("0")); +} + +PluginGroup::PluginGroup(const PluginGroup& other) { + InitFrom(other); +} + +PluginGroup& PluginGroup::operator=(const PluginGroup& other) { + version_ranges_.clear(); + InitFrom(other); + return *this; +} + +/*static*/ +PluginGroup* PluginGroup::FromPluginGroupDefinition( + const PluginGroupDefinition& definition) { + PluginGroup* group = new PluginGroup(ASCIIToUTF16(definition.name), + ASCIIToUTF16(definition.name_matcher), + definition.update_url, + definition.identifier); + for (size_t i = 0; i < definition.num_versions; ++i) + group->version_ranges_.push_back(VersionRange(definition.versions[i])); + return group; +} + +PluginGroup::~PluginGroup() { } + +/*static*/ +std::string PluginGroup::GetIdentifier(const WebPluginInfo& wpi) { +#if defined(OS_POSIX) + return wpi.path.BaseName().value(); +#elif defined(OS_WIN) + return base::SysWideToUTF8(wpi.path.BaseName().value()); +#endif +} + +/*static*/ +std::string PluginGroup::GetLongIdentifier(const WebPluginInfo& wpi) { +#if defined(OS_POSIX) + return wpi.path.value(); +#elif defined(OS_WIN) + return base::SysWideToUTF8(wpi.path.value()); +#endif +} + +/*static*/ +PluginGroup* PluginGroup::FromWebPluginInfo(const WebPluginInfo& wpi) { + // Create a matcher from the name of this plugin. + return new PluginGroup(wpi.name, wpi.name, std::string(), + GetIdentifier(wpi)); +} + +bool PluginGroup::Match(const WebPluginInfo& plugin) const { + if (name_matcher_.empty()) { + return false; + } + + // Look for the name matcher anywhere in the plugin name. + if (plugin.name.find(name_matcher_) == string16::npos) { + return false; + } + + if (version_ranges_.empty()) { + return true; + } + + // There's at least one version range, the plugin's version must be in it. + scoped_ptr plugin_version( + Version::GetVersionFromString(UTF16ToWide(plugin.version))); + if (plugin_version.get() == NULL) { + // No version could be extracted, assume we don't match the range. + return false; + } + + // Match if the plugin is contained in any of the defined VersionRanges. + for (size_t i = 0; i < version_ranges_.size(); ++i) { + if (IsVersionInRange(*plugin_version, version_ranges_[i])) { + return true; + } + } + // None of the VersionRanges matched. + return false; +} + +/* static */ +Version* PluginGroup::CreateVersionFromString(const string16& version_string) { + // Remove spaces and ')' from the version string, + // Replace any instances of 'r', ',' or '(' with a dot. + std::wstring version = UTF16ToWide(version_string); + RemoveChars(version, L") ", &version); + std::replace(version.begin(), version.end(), 'r', '.'); + std::replace(version.begin(), version.end(), ',', '.'); + std::replace(version.begin(), version.end(), '(', '.'); + + return Version::GetVersionFromString(version); +} + +void PluginGroup::UpdateActivePlugin(const WebPluginInfo& plugin) { + // A group is enabled if any of the files are enabled. + if (plugin.enabled) { + if (!enabled_) { + // If this is the first enabled plugin, use its description. + enabled_ = true; + UpdateDescriptionAndVersion(plugin); + } + } else { + // If this is the first plugin and it's disabled, + // use its description for now. + if (description_.empty()) + UpdateDescriptionAndVersion(plugin); + } +} + +void PluginGroup::UpdateDescriptionAndVersion(const WebPluginInfo& plugin) { + description_ = plugin.desc; + if (Version* new_version = CreateVersionFromString(plugin.version)) + version_.reset(new_version); + else + version_.reset(Version::GetVersionFromString("0")); +} + +void PluginGroup::AddPlugin(const WebPluginInfo& plugin, int position) { + // Check if this group already contains this plugin. + for (size_t i = 0; i < web_plugin_infos_.size(); ++i) { + if (web_plugin_infos_[i].name == plugin.name && + web_plugin_infos_[i].version == plugin.version && + FilePath::CompareEqualIgnoreCase(web_plugin_infos_[i].path.value(), + plugin.path.value())) { + return; + } + } + web_plugin_infos_.push_back(plugin); + // The position of this plugin relative to the global list of plugins. + web_plugin_positions_.push_back(position); + UpdateActivePlugin(plugin); +} + +string16 PluginGroup::GetGroupName() const { + if (!group_name_.empty()) + return group_name_; + DCHECK_EQ(1u, web_plugin_infos_.size()); + FilePath::StringType path = + web_plugin_infos_[0].path.BaseName().RemoveExtension().value(); +#if defined(OS_POSIX) + return UTF8ToUTF16(path); +#elif defined(OS_WIN) + return WideToUTF16(path); +#endif +} + +DictionaryValue* PluginGroup::GetSummary() const { + DictionaryValue* result = new DictionaryValue(); + result->SetString("name", GetGroupName()); + result->SetBoolean("enabled", enabled_); + return result; +} + +DictionaryValue* PluginGroup::GetDataForUI() const { + string16 name = GetGroupName(); + DictionaryValue* result = new DictionaryValue(); + result->SetString("name", name); + result->SetString("description", description_); + result->SetString("version", version_->GetString()); + result->SetString("update_url", update_url_); + result->SetBoolean("critical", IsVulnerable()); + + bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(name); + ListValue* plugin_files = new ListValue(); + bool all_plugins_disabled_by_policy = true; + for (size_t i = 0; i < web_plugin_infos_.size(); ++i) { + const WebPluginInfo& web_plugin = web_plugin_infos_[i]; + int priority = web_plugin_positions_[i]; + DictionaryValue* plugin_file = new DictionaryValue(); + plugin_file->SetString("name", web_plugin.name); + plugin_file->SetString("description", web_plugin.desc); + plugin_file->SetString("path", web_plugin.path.value()); + plugin_file->SetString("version", web_plugin.version); + bool plugin_disabled_by_policy = group_disabled_by_policy || + IsPluginNameDisabledByPolicy(web_plugin.name); + if (plugin_disabled_by_policy) { + plugin_file->SetString("enabledMode", "disabledByPolicy"); + } else { + all_plugins_disabled_by_policy = false; + plugin_file->SetString("enabledMode", + web_plugin.enabled ? "enabled" : "disabledByUser"); + } + plugin_file->SetInteger("priority", priority); + + ListValue* mime_types = new ListValue(); + for (std::vector::const_iterator type_it = + web_plugin.mime_types.begin(); + type_it != web_plugin.mime_types.end(); + ++type_it) { + DictionaryValue* mime_type = new DictionaryValue(); + mime_type->SetString("mimeType", type_it->mime_type); + mime_type->SetString("description", type_it->description); + + ListValue* file_extensions = new ListValue(); + for (std::vector::const_iterator ext_it = + type_it->file_extensions.begin(); + ext_it != type_it->file_extensions.end(); + ++ext_it) { + file_extensions->Append(new StringValue(*ext_it)); + } + mime_type->Set("fileExtensions", file_extensions); + + mime_types->Append(mime_type); + } + plugin_file->Set("mimeTypes", mime_types); + + plugin_files->Append(plugin_file); + } + + if (group_disabled_by_policy || all_plugins_disabled_by_policy) { + result->SetString("enabledMode", "disabledByPolicy"); + } else { + result->SetString("enabledMode", enabled_ ? "enabled" : "disabledByUser"); + } + result->Set("plugin_files", plugin_files); + + return result; +} + +/*static*/ +bool PluginGroup::IsVersionInRange(const Version& version, + const VersionRange& range) { + DCHECK(range.low.get() != NULL || range.high.get() == NULL) + << "Lower bound of version range must be defined."; + return (range.low.get() == NULL && range.high.get() == NULL) || + (range.low->CompareTo(version) <= 0 && + (range.high.get() == NULL || range.high->CompareTo(version) > 0)); +} + +/*static*/ +bool PluginGroup::IsPluginOutdated(const Version& plugin_version, + const VersionRange& version_range) { + if (IsVersionInRange(plugin_version, version_range)) { + if (version_range.min.get() && + plugin_version.CompareTo(*version_range.min) < 0) { + return true; + } + } + return false; +} + +// Returns true if the latest version of this plugin group is vulnerable. +bool PluginGroup::IsVulnerable() const { + for (size_t i = 0; i < version_ranges_.size(); ++i) { + if (IsPluginOutdated(*version_, version_ranges_[i])) + return true; + } + return false; +} + +void PluginGroup::DisableOutdatedPlugins() { + description_ = string16(); + enabled_ = false; + + for (std::vector::iterator it = + web_plugin_infos_.begin(); + it != web_plugin_infos_.end(); ++it) { + scoped_ptr version(CreateVersionFromString(it->version)); + if (version.get()) { + for (size_t i = 0; i < version_ranges_.size(); ++i) { + if (IsPluginOutdated(*version, version_ranges_[i])) { + it->enabled = false; + NPAPI::PluginList::Singleton()->DisablePlugin(it->path); + } + } + } + UpdateActivePlugin(*it); + } +} + +void PluginGroup::Enable(bool enable) { + bool enabled_plugin_exists = false; + for (std::vector::iterator it = + web_plugin_infos_.begin(); + it != web_plugin_infos_.end(); ++it) { + if (enable && !IsPluginNameDisabledByPolicy(it->name)) { + NPAPI::PluginList::Singleton()->EnablePlugin(it->path); + it->enabled = true; + enabled_plugin_exists = true; + } else { + it->enabled = false; + NPAPI::PluginList::Singleton()->DisablePlugin(it->path); + } + } + enabled_ = enabled_plugin_exists; +} diff --git a/webkit/glue/plugins/plugin_group.h b/webkit/glue/plugins/plugin_group.h new file mode 100644 index 0000000..5098787 --- /dev/null +++ b/webkit/glue/plugins/plugin_group.h @@ -0,0 +1,205 @@ +// 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 WEBKIT_GLUE_PLUGINS_PLUGIN_GROUP_H_ +#define WEBKIT_GLUE_PLUGINS_PLUGIN_GROUP_H_ +#pragma once + +#include +#include +#include +#include + +#include "base/gtest_prod_util.h" +#include "base/scoped_ptr.h" +#include "base/string16.h" + +class DictionaryValue; +class FilePath; +class Version; +struct WebPluginInfo; + +namespace NPAPI { +class PluginList; +}; + +// Hard-coded version ranges for plugin groups. +struct VersionRangeDefinition { + // Matcher for lowest version matched by this range (inclusive). May be empty + // to match everything iff |version_matcher_high| is also empty. + const char* version_matcher_low; + // Matcher for highest version matched by this range (exclusive). May be empty + // to match anything higher than |version_matcher_low|. + const char* version_matcher_high; + const char* min_version; // Minimum secure version. +}; + +// Hard-coded definitions of plugin groups. +struct PluginGroupDefinition { + const char* identifier; // Unique identifier for this group. + const char* name; // Name of this group. + const char* name_matcher; // Substring matcher for the plugin name. + const VersionRangeDefinition* versions; // List of version ranges. + const size_t num_versions; // Size of the array |versions| points to. + const char* update_url; // Location of latest secure version. +}; + +// Run-time structure to hold version range information. +struct VersionRange { + public: + explicit VersionRange(VersionRangeDefinition definition); + VersionRange(const VersionRange& other); + VersionRange& operator=(const VersionRange& other); + ~VersionRange(); + + std::string low_str; + std::string high_str; + std::string min_str; + scoped_ptr low; + scoped_ptr high; + scoped_ptr min; + private: + void InitFrom(const VersionRange& other); +}; + +// A PluginGroup can match a range of versions of a specific plugin (as defined +// by matching a substring of its name). +// It contains all WebPluginInfo structs (at least one) matching its definition. +// In addition, it knows about a security "baseline", i.e. the minimum version +// of a plugin that is needed in order not to exhibit known security +// vulnerabilities. + +class PluginGroup { + public: + // Used by about:plugins to disable Reader plugin when internal PDF viewer is + // enabled. + static const char* kAdobeReaderGroupName; + + PluginGroup(const PluginGroup& other); + + ~PluginGroup(); + + PluginGroup& operator=(const PluginGroup& other); + + // Configures the set of plugin name patterns for disabling plugins via + // enterprise configuration management. + static void SetPolicyDisabledPluginPatterns(const std::set& set); + + // Tests to see if a plugin is on the blacklist using its name as + // the lookup key. + static bool IsPluginNameDisabledByPolicy(const string16& plugin_name); + + // Tests to see if a plugin is on the blacklist using its path as + // the lookup key. + static bool IsPluginPathDisabledByPolicy(const FilePath& plugin_path); + + // Returns true if the given plugin matches this group. + bool Match(const WebPluginInfo& plugin) const; + + // Adds the given plugin to this group. Provide the position of the + // plugin as given by PluginList so we can display its priority. + void AddPlugin(const WebPluginInfo& plugin, int position); + + // Enables/disables this group. This enables/disables all plugins in the + // group. + void Enable(bool enable); + + // Returns whether the plugin group is enabled or not. + bool Enabled() const { return enabled_; } + + // Returns a unique identifier for this group, if one is defined, or the empty + // string otherwise. + const std::string& identifier() const { return identifier_; } + + // Returns this group's name, or the filename without extension if the name + // is empty. + string16 GetGroupName() const; + + // Returns the description of the highest-priority plug-in in the group. + const string16& description() const { return description_; } + + // Returns a DictionaryValue with data to display in the UI. + DictionaryValue* GetDataForUI() const; + + // Returns a DictionaryValue with data to save in the preferences. + DictionaryValue* GetSummary() const; + + // Returns the update URL. + std::string GetUpdateURL() const { return update_url_; } + + // Returns true if the highest-priority plugin in this group has known + // security problems. + bool IsVulnerable() const; + + // Disables all plugins in this group that are older than the + // minimum version. + void DisableOutdatedPlugins(); + + // Parse a version string as used by a plug-in. This method is more lenient + // in accepting weird version strings than Version::GetFromString(). + static Version* CreateVersionFromString(const string16& version_string); + + private: + typedef std::map PluginMap; + + friend class NPAPI::PluginList; + friend class PluginGroupTest; + friend class TableModelArrayControllerTest; + friend class PluginExceptionsTableModelTest; + + // Generates the (short) identifier string for the given plugin. + static std::string GetIdentifier(const WebPluginInfo& wpi); + + // Generates the long identifier (based on the full file path) for the given + // plugin, to be called when the short identifier is not unique. + static std::string GetLongIdentifier(const WebPluginInfo& wpi); + + // Creates a PluginGroup from a PluginGroupDefinition. The caller takes + // ownership of the created PluginGroup. + static PluginGroup* FromPluginGroupDefinition( + const PluginGroupDefinition& definition); + + // Creates a PluginGroup from a WebPluginInfo. The caller takes ownership of + // the created PluginGroup. + static PluginGroup* FromWebPluginInfo(const WebPluginInfo& wpi); + + // Returns |true| if |version| is contained in [low, high) of |range|. + static bool IsVersionInRange(const Version& version, + const VersionRange& range); + + // Returns |true| iff |plugin_version| is both contained in |version_range| + // and declared outdated (== vulnerable) by it. + static bool IsPluginOutdated(const Version& plugin_version, + const VersionRange& version_range); + + PluginGroup(const string16& group_name, + const string16& name_matcher, + const std::string& update_url, + const std::string& identifier); + + void InitFrom(const PluginGroup& other); + + // Set the description and version for this plugin group from the + // given plug-in. + void UpdateDescriptionAndVersion(const WebPluginInfo& plugin); + + // Updates the active plugin in the group. The active plugin is the first + // enabled one, or if all plugins are disabled, simply the first one. + void UpdateActivePlugin(const WebPluginInfo& plugin); + + static std::set* policy_disabled_plugin_patterns_; + + std::string identifier_; + string16 group_name_; + string16 name_matcher_; + string16 description_; + std::string update_url_; + bool enabled_; + std::vector version_ranges_; + scoped_ptr version_; + std::vector web_plugin_infos_; + std::vector web_plugin_positions_; +}; + +#endif // WEBKIT_GLUE_PLUGINS_PLUGIN_GROUP_H_ diff --git a/webkit/glue/plugins/plugin_group_unittest.cc b/webkit/glue/plugins/plugin_group_unittest.cc new file mode 100644 index 0000000..31dee1e --- /dev/null +++ b/webkit/glue/plugins/plugin_group_unittest.cc @@ -0,0 +1,224 @@ +// 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 "webkit/glue/plugins/plugin_group.h" + +#include +#include + +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "base/version.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/glue/plugins/webplugininfo.h" +#include "webkit/glue/plugins/plugin_list.h" + +static const VersionRangeDefinition kPluginVersionRange[] = { + { "", "", "3.0.44" } +}; +static const VersionRangeDefinition kPlugin3VersionRange[] = { + { "0", "4", "3.0.44" } +}; +static const VersionRangeDefinition kPlugin4VersionRange[] = { + { "4", "5", "4.0.44" } +}; +static const VersionRangeDefinition kPlugin34VersionRange[] = { + { "0", "4", "3.0.44" }, + { "4", "5", "4.0.44" } +}; + +static const PluginGroupDefinition kPluginDef = { + "myplugin", "MyPlugin", "MyPlugin", kPluginVersionRange, 1, + "http://latest/" }; +static const PluginGroupDefinition kPluginDef3 = { + "myplugin-3", "MyPlugin 3", "MyPlugin", kPlugin3VersionRange, 1, + "http://latest" }; +static const PluginGroupDefinition kPluginDef4 = { + "myplugin-4", "MyPlugin 4", "MyPlugin", kPlugin4VersionRange, 1, + "http://latest" }; +static const PluginGroupDefinition kPluginDef34 = { + "myplugin-34", "MyPlugin 3/4", "MyPlugin", kPlugin34VersionRange, 2, + "http://latest" }; +static const PluginGroupDefinition kPluginDefNotVulnerable = { + "myplugin-latest", "MyPlugin", "MyPlugin", NULL, 0, "http://latest" }; + +// name, path, version, desc, mime_types, enabled. +static WebPluginInfo kPlugin2043 = WebPluginInfo( + ASCIIToUTF16("MyPlugin"), ASCIIToUTF16("2.0.43"), + ASCIIToUTF16("MyPlugin version 2.0.43")); +static WebPluginInfo kPlugin3043 = WebPluginInfo( + ASCIIToUTF16("MyPlugin"), ASCIIToUTF16("3.0.43"), + ASCIIToUTF16("MyPlugin version 3.0.43")); +static WebPluginInfo kPlugin3044 = WebPluginInfo( + ASCIIToUTF16("MyPlugin"), ASCIIToUTF16("3.0.44"), + ASCIIToUTF16("MyPlugin version 3.0.44")); +static WebPluginInfo kPlugin3045 = WebPluginInfo( + ASCIIToUTF16("MyPlugin"), ASCIIToUTF16("3.0.45"), + ASCIIToUTF16("MyPlugin version 3.0.45")); +static WebPluginInfo kPlugin4043 = WebPluginInfo( + ASCIIToUTF16("MyPlugin"), ASCIIToUTF16("4.0.43"), + ASCIIToUTF16("MyPlugin version 4.0.43")); + +class PluginGroupTest : public testing::Test { + public: + static PluginGroup* CreatePluginGroup( + const PluginGroupDefinition& definition) { + return PluginGroup::FromPluginGroupDefinition(definition); + } + static PluginGroup* CreatePluginGroup(const WebPluginInfo& wpi) { + return PluginGroup::FromWebPluginInfo(wpi); + } + protected: + virtual void TearDown() { + PluginGroup::SetPolicyDisabledPluginPatterns(std::set()); + } +}; + +TEST(PluginGroupTest, PluginGroupMatch) { + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + kPluginDef3)); + EXPECT_TRUE(group->Match(kPlugin3045)); + group->AddPlugin(kPlugin3045, 0); + EXPECT_FALSE(group->IsVulnerable()); +} + +TEST(PluginGroupTest, PluginGroupMatchCorrectVersion) { + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + kPluginDef3)); + EXPECT_TRUE(group->Match(kPlugin2043)); + EXPECT_TRUE(group->Match(kPlugin3043)); + EXPECT_FALSE(group->Match(kPlugin4043)); + + group.reset(PluginGroupTest::CreatePluginGroup(kPluginDef4)); + EXPECT_FALSE(group->Match(kPlugin2043)); + EXPECT_FALSE(group->Match(kPlugin3043)); + EXPECT_TRUE(group->Match(kPlugin4043)); + + group.reset(PluginGroupTest::CreatePluginGroup(kPluginDef34)); + EXPECT_TRUE(group->Match(kPlugin2043)); + EXPECT_TRUE(group->Match(kPlugin3043)); + EXPECT_TRUE(group->Match(kPlugin4043)); +} + +TEST(PluginGroupTest, PluginGroupDescription) { + string16 desc3043(ASCIIToUTF16("MyPlugin version 3.0.43")); + string16 desc3045(ASCIIToUTF16("MyPlugin version 3.0.45")); + + PluginGroupDefinition plugindefs[] = { kPluginDef3, kPluginDef34 }; + for (size_t i = 0; i < 2; ++i) { + WebPluginInfo plugin3043(kPlugin3043); + WebPluginInfo plugin3045(kPlugin3045); + { + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + plugindefs[i])); + EXPECT_TRUE(group->Match(plugin3043)); + group->AddPlugin(plugin3043, 0); + EXPECT_EQ(desc3043, group->description()); + EXPECT_TRUE(group->IsVulnerable()); + EXPECT_TRUE(group->Match(plugin3045)); + group->AddPlugin(plugin3045, 1); + EXPECT_EQ(desc3043, group->description()); + EXPECT_TRUE(group->IsVulnerable()); + } + + { + // Disable the first plugin. + plugin3043.enabled = false; + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + plugindefs[i])); + EXPECT_TRUE(group->Match(plugin3043)); + group->AddPlugin(plugin3043, 0); + EXPECT_EQ(desc3043, group->description()); + EXPECT_TRUE(group->IsVulnerable()); + EXPECT_FALSE(group->Enabled()); + EXPECT_TRUE(group->Match(plugin3045)); + group->AddPlugin(plugin3045, 1); + EXPECT_EQ(desc3045, group->description()); + EXPECT_FALSE(group->IsVulnerable()); + } + + { + // Disable the second plugin. + plugin3045.enabled = false; + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + plugindefs[i])); + EXPECT_TRUE(group->Match(plugin3043)); + group->AddPlugin(plugin3043, 1); + EXPECT_EQ(desc3043, group->description()); + EXPECT_TRUE(group->IsVulnerable()); + EXPECT_TRUE(group->Match(plugin3045)); + group->AddPlugin(plugin3045, 0); + EXPECT_EQ(desc3043, group->description()); + EXPECT_TRUE(group->IsVulnerable()); + } + } +} + +TEST(PluginGroupTest, PluginGroupDefinition) { + const PluginGroupDefinition* definitions = + NPAPI::PluginList::GetPluginGroupDefinitions(); + for (size_t i = 0; + i < NPAPI::PluginList::GetPluginGroupDefinitionsSize(); + ++i) { + scoped_ptr def_group( + PluginGroupTest::CreatePluginGroup(definitions[i])); + ASSERT_TRUE(def_group.get() != NULL); + EXPECT_FALSE(def_group->Match(kPlugin2043)); + } +} + +TEST(PluginGroupTest, DisableOutdated) { + PluginGroupDefinition plugindefs[] = { kPluginDef3, kPluginDef34 }; + for (size_t i = 0; i < 2; ++i) { + scoped_ptr group(PluginGroupTest::CreatePluginGroup( + plugindefs[i])); + group->AddPlugin(kPlugin3043, 0); + group->AddPlugin(kPlugin3045, 1); + EXPECT_EQ(ASCIIToUTF16("MyPlugin version 3.0.43"), group->description()); + EXPECT_TRUE(group->IsVulnerable()); + + group->DisableOutdatedPlugins(); + EXPECT_EQ(ASCIIToUTF16("MyPlugin version 3.0.45"), group->description()); + EXPECT_FALSE(group->IsVulnerable()); + } +} + +TEST(PluginGroupTest, VersionExtraction) { + // Some real-world plugin versions (spaces, commata, parentheses, 'r', oh my) + const char* versions[][2] = { + { "7.6.6 (1671)", "7.6.6.1671" }, // Quicktime + { "2, 0, 0, 254", "2.0.0.254" }, // DivX + { "3, 0, 0, 0", "3.0.0.0" }, // Picasa + { "1, 0, 0, 1", "1.0.0.1" }, // Earth + { "10,0,45,2", "10.0.45.2" }, // Flash + { "11.5.7r609", "11.5.7.609"} // Shockwave + }; + + for (size_t i = 0; i < arraysize(versions); i++) { + const WebPluginInfo plugin = WebPluginInfo( + ASCIIToUTF16("Blah Plugin"), ASCIIToUTF16(versions[i][0]), string16()); + scoped_ptr group(PluginGroupTest::CreatePluginGroup(plugin)); + EXPECT_TRUE(group->Match(plugin)); + group->AddPlugin(plugin, 0); + scoped_ptr data(group->GetDataForUI()); + std::string version; + data->GetString("version", &version); + EXPECT_EQ(versions[i][1], version); + } +} + +TEST(PluginGroupTest, DisabledByPolicy) { + std::set disabled_plugins; + disabled_plugins.insert(ASCIIToUTF16("Disable this!")); + disabled_plugins.insert(ASCIIToUTF16("*Google*")); + PluginGroup::SetPolicyDisabledPluginPatterns(disabled_plugins); + + EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(ASCIIToUTF16("42"))); + EXPECT_TRUE(PluginGroup::IsPluginNameDisabledByPolicy( + ASCIIToUTF16("Disable this!"))); + EXPECT_TRUE(PluginGroup::IsPluginNameDisabledByPolicy( + ASCIIToUTF16("Google Earth"))); +} diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc new file mode 100644 index 0000000..28aba02 --- /dev/null +++ b/webkit/glue/plugins/plugin_host.cc @@ -0,0 +1,1111 @@ +// 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 "webkit/glue/plugins/plugin_host.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "base/string_piece.h" +#include "base/string_util.h" +#if defined(OS_MACOSX) +#include "base/sys_info.h" +#endif +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "net/base/net_util.h" +#include "third_party/npapi/bindings/npapi_extensions.h" +#include "third_party/npapi/bindings/npruntime.h" +#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" +#include "third_party/WebKit/WebKit/chromium/public/WebKit.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/default_plugin_shared.h" +#include "webkit/glue/plugins/npapi_extension_thunk.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/plugins/webplugininfo.h" + +using WebKit::WebBindings; + +// Finds a PluginInstance from an NPP. +// The caller must take a reference if needed. +static NPAPI::PluginInstance* FindInstance(NPP id) { + if (id == NULL) { + return NULL; + } + return reinterpret_cast(id->ndata); +} + +#if defined(OS_MACOSX) +// Returns true if the OS supports shared accelerated surfaces via IOSurface. +// This is true on Snow Leopard and higher. +static bool SupportsSharingAcceleratedSurfaces() { + int32 major, minor, bugfix; + base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); + return major > 10 || (major == 10 && minor > 5); +} +#endif + +namespace NPAPI { + +scoped_refptr PluginHost::singleton_; + +PluginHost::PluginHost() { + InitializeHostFuncs(); +} + +PluginHost::~PluginHost() { +} + +PluginHost *PluginHost::Singleton() { + if (singleton_.get() == NULL) { + singleton_ = new PluginHost(); + } + + DCHECK(singleton_.get() != NULL); + return singleton_; +} + +void PluginHost::InitializeHostFuncs() { + memset(&host_funcs_, 0, sizeof(host_funcs_)); + host_funcs_.size = sizeof(host_funcs_); + host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR); + + // The "basic" functions + host_funcs_.geturl = &NPN_GetURL; + host_funcs_.posturl = &NPN_PostURL; + host_funcs_.requestread = &NPN_RequestRead; + host_funcs_.newstream = &NPN_NewStream; + host_funcs_.write = &NPN_Write; + host_funcs_.destroystream = &NPN_DestroyStream; + host_funcs_.status = &NPN_Status; + host_funcs_.uagent = &NPN_UserAgent; + host_funcs_.memalloc = &NPN_MemAlloc; + host_funcs_.memfree = &NPN_MemFree; + host_funcs_.memflush = &NPN_MemFlush; + host_funcs_.reloadplugins = &NPN_ReloadPlugins; + + // We don't implement java yet + host_funcs_.getJavaEnv = &NPN_GetJavaEnv; + host_funcs_.getJavaPeer = &NPN_GetJavaPeer; + + // Advanced functions we implement + host_funcs_.geturlnotify = &NPN_GetURLNotify; + host_funcs_.posturlnotify = &NPN_PostURLNotify; + host_funcs_.getvalue = &NPN_GetValue; + host_funcs_.setvalue = &NPN_SetValue; + host_funcs_.invalidaterect = &NPN_InvalidateRect; + host_funcs_.invalidateregion = &NPN_InvalidateRegion; + host_funcs_.forceredraw = &NPN_ForceRedraw; + + // These come from the Javascript Engine + host_funcs_.getstringidentifier = WebBindings::getStringIdentifier; + host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers; + host_funcs_.getintidentifier = WebBindings::getIntIdentifier; + host_funcs_.identifierisstring = WebBindings::identifierIsString; + host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier; + host_funcs_.intfromidentifier = WebBindings::intFromIdentifier; + host_funcs_.createobject = WebBindings::createObject; + host_funcs_.retainobject = WebBindings::retainObject; + host_funcs_.releaseobject = WebBindings::releaseObject; + host_funcs_.invoke = WebBindings::invoke; + host_funcs_.invokeDefault = WebBindings::invokeDefault; + host_funcs_.evaluate = WebBindings::evaluate; + host_funcs_.getproperty = WebBindings::getProperty; + host_funcs_.setproperty = WebBindings::setProperty; + host_funcs_.removeproperty = WebBindings::removeProperty; + host_funcs_.hasproperty = WebBindings::hasProperty; + host_funcs_.hasmethod = WebBindings::hasMethod; + host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue; + host_funcs_.setexception = WebBindings::setException; + host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState; + host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState; + host_funcs_.enumerate = WebBindings::enumerate; + host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall; + host_funcs_.construct = WebBindings::construct; + host_funcs_.getvalueforurl = NPN_GetValueForURL; + host_funcs_.setvalueforurl = NPN_SetValueForURL; + host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo; + host_funcs_.scheduletimer = NPN_ScheduleTimer; + host_funcs_.unscheduletimer = NPN_UnscheduleTimer; + host_funcs_.popupcontextmenu = NPN_PopUpContextMenu; + host_funcs_.convertpoint = NPN_ConvertPoint; + host_funcs_.handleevent = NPN_HandleEvent; + host_funcs_.unfocusinstance = NPN_UnfocusInstance; + host_funcs_.urlredirectresponse = NPN_URLRedirectResponse; +} + +void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) { + // When running in the plugin process, we need to patch the NPN functions + // that the plugin calls to interact with NPObjects that we give. Otherwise + // the plugin will call the v8 NPN functions, which won't work since we have + // an NPObjectProxy and not a real v8 implementation. + if (overrides->invoke) + host_funcs_.invoke = overrides->invoke; + + if (overrides->invokeDefault) + host_funcs_.invokeDefault = overrides->invokeDefault; + + if (overrides->evaluate) + host_funcs_.evaluate = overrides->evaluate; + + if (overrides->getproperty) + host_funcs_.getproperty = overrides->getproperty; + + if (overrides->setproperty) + host_funcs_.setproperty = overrides->setproperty; + + if (overrides->removeproperty) + host_funcs_.removeproperty = overrides->removeproperty; + + if (overrides->hasproperty) + host_funcs_.hasproperty = overrides->hasproperty; + + if (overrides->hasmethod) + host_funcs_.hasmethod = overrides->hasmethod; + + if (overrides->setexception) + host_funcs_.setexception = overrides->setexception; + + if (overrides->enumerate) + host_funcs_.enumerate = overrides->enumerate; +} + +bool PluginHost::SetPostData(const char* buf, + uint32 length, + std::vector* names, + std::vector* values, + std::vector* body) { + // Use a state table to do the parsing. Whitespace must be + // trimmed after the fact if desired. In our case, we actually + // don't care about the whitespace, because we're just going to + // pass this back into another POST. This function strips out the + // "Content-length" header and does not append it to the request. + + // + // This parser takes action only on state changes. + // + // Transition table: + // : \n NULL Other + // 0 GetHeader 1 2 4 0 + // 1 GetValue 1 0 3 1 + // 2 GetData 2 2 3 2 + // 3 DONE + // 4 ERR + // + enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER }; + enum { GETNAME, GETVALUE, GETDATA, DONE, ERR }; + int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME }, + { GETVALUE, GETNAME, DONE, GETVALUE }, + { GETDATA, GETDATA, DONE, GETDATA } }; + std::string name, value; + const char* ptr = static_cast(buf); + const char* start = ptr; + int state = GETNAME; // initial state + bool done = false; + bool err = false; + do { + int input; + + // Translate the current character into an input + // for the state table. + switch (*ptr) { + case ':' : + input = INPUT_COLON; + break; + case '\n': + input = INPUT_NEWLINE; + break; + case 0 : + input = INPUT_NULL; + break; + default : + input = INPUT_OTHER; + break; + } + + int newstate = statemachine[state][input]; + + // Take action based on the new state. + if (state != newstate) { + switch (newstate) { + case GETNAME: + // Got a value. + value = std::string(start, ptr - start); + TrimWhitespace(value, TRIM_ALL, &value); + // If the name field is empty, we'll skip this header + // but we won't error out. + if (!name.empty() && name != "content-length") { + names->push_back(name); + values->push_back(value); + } + start = ptr + 1; + break; + case GETVALUE: + // Got a header. + name = StringToLowerASCII(std::string(start, ptr - start)); + TrimWhitespace(name, TRIM_ALL, &name); + start = ptr + 1; + break; + case GETDATA: { + // Finished headers, now get body + if (*ptr) + start = ptr + 1; + size_t previous_size = body->size(); + size_t new_body_size = length - static_cast(start - buf); + body->resize(previous_size + new_body_size); + if (!body->empty()) + memcpy(&body->front() + previous_size, start, new_body_size); + done = true; + break; + } + case ERR: + // error + err = true; + done = true; + break; + } + } + state = newstate; + ptr++; + } while (!done); + + return !err; +} + +} // namespace NPAPI + +extern "C" { + +// Allocates memory from the host's memory space. +void* NPN_MemAlloc(uint32_t size) { + scoped_refptr host(NPAPI::PluginHost::Singleton()); + if (host != NULL) { + // Note: We must use the same allocator/deallocator + // that is used by the javascript library, as some of the + // JS APIs will pass memory to the plugin which the plugin + // will attempt to free. + return malloc(size); + } + return NULL; +} + +// Deallocates memory from the host's memory space +void NPN_MemFree(void* ptr) { + scoped_refptr host(NPAPI::PluginHost::Singleton()); + if (host != NULL) { + if (ptr != NULL && ptr != reinterpret_cast(-1)) + free(ptr); + } +} + +// Requests that the host free a specified amount of memory. +uint32_t NPN_MemFlush(uint32_t size) { + // This is not relevant on Windows; MAC specific + return size; +} + +// This is for dynamic discovery of new plugins. +// Should force a re-scan of the plugins directory to load new ones. +void NPN_ReloadPlugins(NPBool reload_pages) { + WebKit::resetPluginCache(reload_pages ? true : false); +} + +// Requests a range of bytes for a seekable stream. +NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { + if (!stream || !range_list) + return NPERR_GENERIC_ERROR; + + scoped_refptr plugin( + reinterpret_cast(stream->ndata)); + if (!plugin.get()) + return NPERR_GENERIC_ERROR; + + plugin->RequestRead(stream, range_list); + return NPERR_NO_ERROR; +} + +// Generic form of GetURL for common code between GetURL and GetURLNotify. +static NPError GetURLNotify(NPP id, + const char* url, + const char* target, + bool notify, + void* notify_data) { + if (!url) + return NPERR_INVALID_URL; + + scoped_refptr plugin(FindInstance(id)); + if (!plugin.get()) { + return NPERR_GENERIC_ERROR; + } + + plugin->RequestURL(url, "GET", target, NULL, 0, notify, notify_data); + return NPERR_NO_ERROR; +} + +// Requests creation of a new stream with the contents of the +// specified URL; gets notification of the result. +NPError NPN_GetURLNotify(NPP id, + const char* url, + const char* target, + void* notify_data) { + // This is identical to NPN_GetURL, but after finishing, the + // browser will call NPP_URLNotify to inform the plugin that + // it has completed. + + // According to the NPAPI documentation, if target == _self + // or a parent to _self, the browser should return NPERR_INVALID_PARAM, + // because it can't notify the plugin once deleted. This is + // absolutely false; firefox doesn't do this, and Flash relies on + // being able to use this. + + // Also according to the NPAPI documentation, we should return + // NPERR_INVALID_URL if the url requested is not valid. However, + // this would require that we synchronously start fetching the + // URL. That just isn't practical. As such, there really is + // no way to return this error. From looking at the Firefox + // implementation, it doesn't look like Firefox does this either. + + return GetURLNotify(id, url, target, true, notify_data); +} + +NPError NPN_GetURL(NPP id, const char* url, const char* target) { + // Notes: + // Request from the Plugin to fetch content either for the plugin + // or to be placed into a browser window. + // + // If target == null, the browser fetches content and streams to plugin. + // otherwise, the browser loads content into an existing browser frame. + // If the target is the window/frame containing the plugin, the plugin + // may be destroyed. + // If the target is _blank, a mailto: or news: url open content in a new + // browser window + // If the target is _self, no other instance of the plugin is created. The + // plugin continues to operate in its own window + + return GetURLNotify(id, url, target, false, 0); +} + +// Generic form of PostURL for common code between PostURL and PostURLNotify. +static NPError PostURLNotify(NPP id, + const char* url, + const char* target, + uint32_t len, + const char* buf, + NPBool file, + bool notify, + void* notify_data) { + if (!url) + return NPERR_INVALID_URL; + + scoped_refptr plugin(FindInstance(id)); + if (!plugin.get()) { + NOTREACHED(); + return NPERR_GENERIC_ERROR; + } + + std::string post_file_contents; + + if (file) { + // Post data to be uploaded from a file. This can be handled in two + // ways. + // 1. Read entire file and send the contents as if it was a post data + // specified in the argument + // 2. Send just the file details and read them in the browser at the + // time of sending the request. + // Approach 2 is more efficient but complicated. Approach 1 has a major + // drawback of sending potentially large data over two IPC hops. In a way + // 'large data over IPC' problem exists as it is in case of plugin giving + // the data directly instead of in a file. + // Currently we are going with the approach 1 to get the feature working. + // We can optimize this later with approach 2. + + // TODO(joshia): Design a scheme to send a file descriptor instead of + // entire file contents across. + + // Security alert: + // --------------- + // Here we are blindly uploading whatever file requested by a plugin. + // This is risky as someone could exploit a plugin to send private + // data in arbitrary locations. + // A malicious (non-sandboxed) plugin has unfeterred access to OS + // resources and can do this anyway without using browser's HTTP stack. + // FWIW, Firefox and Safari don't perform any security checks. + + if (!buf) + return NPERR_FILE_NOT_FOUND; + + std::string file_path_ascii(buf); + FilePath file_path; + static const char kFileUrlPrefix[] = "file:"; + if (StartsWithASCII(file_path_ascii, kFileUrlPrefix, false)) { + GURL file_url(file_path_ascii); + DCHECK(file_url.SchemeIsFile()); + net::FileURLToFilePath(file_url, &file_path); + } else { + file_path = FilePath::FromWStringHack( + base::SysNativeMBToWide(file_path_ascii)); + } + + base::PlatformFileInfo post_file_info = {0}; + if (!file_util::GetFileInfo(file_path, &post_file_info) || + post_file_info.is_directory) + return NPERR_FILE_NOT_FOUND; + + if (!file_util::ReadFileToString(file_path, &post_file_contents)) + return NPERR_FILE_NOT_FOUND; + + buf = post_file_contents.c_str(); + len = post_file_contents.size(); + } + + // The post data sent by a plugin contains both headers + // and post data. Example: + // Content-type: text/html + // Content-length: 200 + // + // <200 bytes of content here> + // + // Unfortunately, our stream needs these broken apart, + // so we need to parse the data and set headers and data + // separately. + plugin->RequestURL(url, "POST", target, buf, len, notify, notify_data); + return NPERR_NO_ERROR; +} + +NPError NPN_PostURLNotify(NPP id, + const char* url, + const char* target, + uint32_t len, + const char* buf, + NPBool file, + void* notify_data) { + return PostURLNotify(id, url, target, len, buf, file, true, notify_data); +} + +NPError NPN_PostURL(NPP id, + const char* url, + const char* target, + uint32_t len, + const char* buf, + NPBool file) { + // POSTs data to an URL, either from a temp file or a buffer. + // If file is true, buf contains a temp file (which host will delete after + // completing), and len contains the length of the filename. + // If file is false, buf contains the data to send, and len contains the + // length of the buffer + // + // If target is null, + // server response is returned to the plugin + // If target is _current, _self, or _top, + // server response is written to the plugin window and plugin is unloaded. + // If target is _new or _blank, + // server response is written to a new browser window + // If target is an existing frame, + // server response goes to that frame. + // + // For protocols other than FTP + // file uploads must be line-end converted from \r\n to \n + // + // Note: you cannot specify headers (even a blank line) in a memory buffer, + // use NPN_PostURLNotify + + return PostURLNotify(id, url, target, len, buf, file, false, 0); +} + +NPError NPN_NewStream(NPP id, + NPMIMEType type, + const char* target, + NPStream** stream) { + // Requests creation of a new data stream produced by the plugin, + // consumed by the browser. + // + // Browser should put this stream into a window target. + // + // TODO: implement me + DVLOG(1) << "NPN_NewStream is not implemented yet."; + return NPERR_GENERIC_ERROR; +} + +int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) { + // Writes data to an existing Plugin-created stream. + + // TODO: implement me + DVLOG(1) << "NPN_Write is not implemented yet."; + return NPERR_GENERIC_ERROR; +} + +NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) { + // Destroys a stream (could be created by plugin or browser). + // + // Reasons: + // NPRES_DONE - normal completion + // NPRES_USER_BREAK - user terminated + // NPRES_NETWORK_ERROR - network error (all errors fit here?) + // + // + + scoped_refptr plugin(FindInstance(id)); + if (plugin.get() == NULL) { + NOTREACHED(); + return NPERR_GENERIC_ERROR; + } + + return plugin->NPP_DestroyStream(stream, reason); +} + +const char* NPN_UserAgent(NPP id) { +#if defined(OS_WIN) + // Flash passes in a null id during the NP_initialize call. We need to + // default to the Mozilla user agent if we don't have an NPP instance or + // else Flash won't request windowless mode. + bool use_mozilla_user_agent = true; + if (id) { + scoped_refptr plugin = FindInstance(id); + if (plugin.get() && !plugin->use_mozilla_user_agent()) + use_mozilla_user_agent = false; + } + + if (use_mozilla_user_agent) + return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) " + "Gecko/20061103 Firefox/2.0a1"; +#elif defined(OS_MACOSX) + // Silverlight 4 doesn't handle events correctly unless we claim to be Safari. + scoped_refptr plugin; + if (id) + plugin = FindInstance(id); + if (plugin.get()) { + WebPluginInfo plugin_info = plugin->plugin_lib()->plugin_info(); + if (plugin_info.name == ASCIIToUTF16("Silverlight Plug-In") && + StartsWith(plugin_info.version, ASCIIToUTF16("4."), false)) { + return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) " + "AppleWebKit/534.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16"; + } + } +#endif + + return webkit_glue::GetUserAgent(GURL()).c_str(); +} + +void NPN_Status(NPP id, const char* message) { + // Displays a message on the status line of the browser window. + + // TODO: implement me + DVLOG(1) << "NPN_Status is not implemented yet."; +} + +void NPN_InvalidateRect(NPP id, NPRect *invalidRect) { + // Invalidates specified drawing area prior to repainting or refreshing a + // windowless plugin + + // Before a windowless plugin can refresh part of its drawing area, it must + // first invalidate it. This function causes the NPP_HandleEvent method to + // pass an update event or a paint message to the plug-in. After calling + // this method, the plug-in recieves a paint message asynchronously. + + // The browser redraws invalid areas of the document and any windowless + // plug-ins at regularly timed intervals. To force a paint message, the + // plug-in can call NPN_ForceRedraw after calling this method. + + scoped_refptr plugin(FindInstance(id)); + if (plugin.get() && plugin->webplugin()) { + if (invalidRect) { +#if defined(OS_WIN) + if (!plugin->windowless()) { + RECT rect = {0}; + rect.left = invalidRect->left; + rect.right = invalidRect->right; + rect.top = invalidRect->top; + rect.bottom = invalidRect->bottom; + ::InvalidateRect(plugin->window_handle(), &rect, false); + return; + } +#endif + gfx::Rect rect(invalidRect->left, + invalidRect->top, + invalidRect->right - invalidRect->left, + invalidRect->bottom - invalidRect->top); + plugin->webplugin()->InvalidateRect(rect); + } else { + plugin->webplugin()->Invalidate(); + } + } +} + +void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) { + // Invalidates a specified drawing region prior to repainting + // or refreshing a window-less plugin. + // + // Similar to NPN_InvalidateRect. + + // TODO: this is overkill--add platform-specific region handling (at the + // very least, fetch the region's bounding box and pass it to InvalidateRect). + scoped_refptr plugin(FindInstance(id)); + DCHECK(plugin.get() != NULL); + if (plugin.get() && plugin->webplugin()) + plugin->webplugin()->Invalidate(); +} + +void NPN_ForceRedraw(NPP id) { + // Forces repaint for a windowless plug-in. + // + // We deliberately do not implement this; we don't want plugins forcing + // synchronous paints. +} + +NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) { + // Allows the plugin to query the browser for information + // + // Variables: + // NPNVxDisplay (unix only) + // NPNVxtAppContext (unix only) + // NPNVnetscapeWindow (win only) - Gets the native window on which the + // plug-in drawing occurs, returns HWND + // NPNVjavascriptEnabledBool: tells whether Javascript is enabled + // NPNVasdEnabledBool: tells whether SmartUpdate is enabled + // NPNVOfflineBool: tells whether offline-mode is enabled + + NPError rv = NPERR_GENERIC_ERROR; + + switch (static_cast(variable)) { + case NPNVWindowNPObject: { + scoped_refptr plugin(FindInstance(id)); + NPObject *np_object = plugin->webplugin()->GetWindowScriptNPObject(); + // Return value is expected to be retained, as + // described here: + // + if (np_object) { + WebBindings::retainObject(np_object); + void **v = (void **)value; + *v = np_object; + rv = NPERR_NO_ERROR; + } else { + NOTREACHED(); + } + break; + } + case NPNVPluginElementNPObject: { + scoped_refptr plugin(FindInstance(id)); + NPObject *np_object = plugin->webplugin()->GetPluginElement(); + // Return value is expected to be retained, as + // described here: + // + if (np_object) { + WebBindings::retainObject(np_object); + void** v = static_cast(value); + *v = np_object; + rv = NPERR_NO_ERROR; + } else { + NOTREACHED(); + } + break; + } + #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins. + case NPNVnetscapeWindow: { + scoped_refptr plugin = FindInstance(id); + if (!plugin.get()) { + NOTREACHED(); + return NPERR_GENERIC_ERROR; + } + gfx::PluginWindowHandle handle = plugin->window_handle(); + *((void**)value) = (void*)handle; + rv = NPERR_NO_ERROR; + break; + } + #endif + case NPNVjavascriptEnabledBool: { + // yes, JS is enabled. + *((void**)value) = (void*)1; + rv = NPERR_NO_ERROR; + break; + } + #if defined(TOOLKIT_USES_GTK) + case NPNVToolkit: + // Tell them we are GTK2. (The alternative is GTK 1.2.) + *reinterpret_cast(value) = NPNVGtk2; + rv = NPERR_NO_ERROR; + break; + + case NPNVSupportsXEmbedBool: + *reinterpret_cast(value) = true; + rv = NPERR_NO_ERROR; + break; + #endif + case NPNVSupportsWindowless: { + NPBool* supports_windowless = reinterpret_cast(value); + *supports_windowless = true; + rv = NPERR_NO_ERROR; + break; + } + case NPNVprivateModeBool: { + NPBool* private_mode = reinterpret_cast(value); + scoped_refptr plugin(FindInstance(id)); + *private_mode = plugin->webplugin()->IsOffTheRecord(); + rv = NPERR_NO_ERROR; + break; + } + case default_plugin::kMissingPluginStatusStart + + default_plugin::MISSING_PLUGIN_AVAILABLE: + // fall through + case default_plugin::kMissingPluginStatusStart + + default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: { + // This is a hack for the default plugin to send notification to + // renderer. Even though we check if the plugin is the default plugin, + // we still need to worry about future standard change that may conflict + // with the variable definition, in order to avoid duplicate case clauses + // in this big switch statement. + scoped_refptr plugin(FindInstance(id)); + if (plugin->plugin_lib()->plugin_info().path.value() == + kDefaultPluginLibraryName) { + plugin->webplugin()->OnMissingPluginStatus( + variable - default_plugin::kMissingPluginStatusStart); + } + break; + } + #if defined(OS_MACOSX) + case NPNVpluginDrawingModel: { + // return the drawing model that was negotiated when we initialized. + scoped_refptr plugin(FindInstance(id)); + *reinterpret_cast(value) = plugin->drawing_model(); + rv = NPERR_NO_ERROR; + break; + } +#ifndef NP_NO_QUICKDRAW + case NPNVsupportsQuickDrawBool: { + // We do not admit to supporting the QuickDraw drawing model. The logic + // here is that our QuickDraw plugin support is so rudimentary that we + // only want to use it as a fallback to keep plugins from crashing: if a + // plugin knows enough to ask, we want them to use CoreGraphics. + NPBool* supports_qd = reinterpret_cast(value); + *supports_qd = false; + rv = NPERR_NO_ERROR; + break; + } +#endif + case NPNVsupportsCoreGraphicsBool: +#ifndef NP_NO_CARBON + case NPNVsupportsCarbonBool: +#endif + case NPNVsupportsCocoaBool: { + // we do support these drawing and event models. + NPBool* supports_model = reinterpret_cast(value); + *supports_model = true; + rv = NPERR_NO_ERROR; + break; + } + case NPNVsupportsCoreAnimationBool: { + // We only support the Core Animation model on 10.6 and higher + // TODO(stuartmorgan): Once existing CA plugins have implemented the + // invalidating version, remove support for this one. + NPBool* supports_model = reinterpret_cast(value); + *supports_model = SupportsSharingAcceleratedSurfaces() ? true : false; + rv = NPERR_NO_ERROR; + break; + } + case NPNVsupportsInvalidatingCoreAnimationBool: { + NPBool* supports_model = reinterpret_cast(value); + *supports_model = true; + rv = NPERR_NO_ERROR; + break; + } + case NPNVsupportsOpenGLBool: { + // This drawing model was never widely supported, and we don't plan to + // support it. + NPBool* supports_model = reinterpret_cast(value); + *supports_model = false; + rv = NPERR_NO_ERROR; + break; + } + #endif // OS_MACOSX + case NPNVPepperExtensions: + // Available for any plugin that attempts to get it. + // If the plugin is not started in a Pepper implementation, it + // will likely fail when it tries to use any of the functions + // attached to the extension vector. + rv = NPAPI::GetPepperExtensionsFunctions(value); + break; + default: + DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet."; + break; + } + return rv; +} + +NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { + // Allows the plugin to set various modes + + scoped_refptr plugin(FindInstance(id)); + switch(variable) { + case NPPVpluginWindowBool: { + // Sets windowless mode for display of the plugin + // Note: the documentation at + // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When + // value is NULL, the mode is set to true. This is the same way Mozilla + // works. + plugin->set_windowless(value == 0); + return NPERR_NO_ERROR; + } + case NPPVpluginTransparentBool: { + // Sets transparent mode for display of the plugin + // + // Transparent plugins require the browser to paint the background + // before having the plugin paint. By default, windowless plugins + // are transparent. Making a windowless plugin opaque means that + // the plugin does not require the browser to paint the background. + bool mode = (value != 0); + plugin->set_transparent(mode); + return NPERR_NO_ERROR; + } + case NPPVjavascriptPushCallerBool: + // Specifies whether you are pushing or popping the JSContext off. + // the stack + // TODO: implement me + DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not " + "implemented."; + return NPERR_GENERIC_ERROR; + case NPPVpluginKeepLibraryInMemory: + // Tells browser that plugin library should live longer than usual. + // TODO: implement me + DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not " + "implemented."; + return NPERR_GENERIC_ERROR; + #if defined(OS_MACOSX) + case NPPVpluginDrawingModel: { + int model = reinterpret_cast(value); + if (model == NPDrawingModelCoreGraphics || + model == NPDrawingModelInvalidatingCoreAnimation || + (model == NPDrawingModelCoreAnimation && + SupportsSharingAcceleratedSurfaces())) { + plugin->set_drawing_model(static_cast(model)); + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; + } + case NPPVpluginEventModel: { + // we support Carbon and Cocoa event models + int model = reinterpret_cast(value); + switch (model) { +#ifndef NP_NO_CARBON + case NPEventModelCarbon: +#endif + case NPEventModelCocoa: + plugin->set_event_model(static_cast(model)); + return NPERR_NO_ERROR; + break; + } + return NPERR_GENERIC_ERROR; + } + #endif + default: + // TODO: implement me + DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented."; + break; + } + + NOTREACHED(); + return NPERR_GENERIC_ERROR; +} + +void* NPN_GetJavaEnv() { + // TODO: implement me + DVLOG(1) << "NPN_GetJavaEnv is not implemented."; + return NULL; +} + +void* NPN_GetJavaPeer(NPP) { + // TODO: implement me + DVLOG(1) << "NPN_GetJavaPeer is not implemented."; + return NULL; +} + +void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) + plugin->PushPopupsEnabledState(enabled ? true : false); +} + +void NPN_PopPopupsEnabledState(NPP id) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) + plugin->PopPopupsEnabledState(); +} + +void NPN_PluginThreadAsyncCall(NPP id, + void (*func)(void*), + void* user_data) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) + plugin->PluginThreadAsyncCall(func, user_data); +} + +NPError NPN_GetValueForURL(NPP id, + NPNURLVariable variable, + const char* url, + char** value, + uint32_t* len) { + if (!id) + return NPERR_INVALID_PARAM; + + if (!url || !*url || !len) + return NPERR_INVALID_URL; + + *len = 0; + std::string result; + + switch (variable) { + case NPNURLVProxy: { + result = "DIRECT"; + if (!webkit_glue::FindProxyForUrl(GURL((std::string(url))), &result)) + return NPERR_GENERIC_ERROR; + + break; + } + case NPNURLVCookie: { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NPERR_GENERIC_ERROR; + + webkit_glue::WebPlugin* webplugin = plugin->webplugin(); + if (!webplugin) + return NPERR_GENERIC_ERROR; + + // Bypass third-party cookie blocking by using the url as the + // first_party_for_cookies. + GURL cookies_url((std::string(url))); + result = webplugin->GetCookies(cookies_url, cookies_url); + break; + } + default: + return NPERR_GENERIC_ERROR; + } + + // Allocate this using the NPAPI allocator. The plugin will call + // NPN_Free to free this. + *value = static_cast(NPN_MemAlloc(result.length() + 1)); + base::strlcpy(*value, result.c_str(), result.length() + 1); + *len = result.length(); + + return NPERR_NO_ERROR; +} + +NPError NPN_SetValueForURL(NPP id, + NPNURLVariable variable, + const char* url, + const char* value, + uint32_t len) { + if (!id) + return NPERR_INVALID_PARAM; + + if (!url || !*url) + return NPERR_INVALID_URL; + + switch (variable) { + case NPNURLVCookie: { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return NPERR_GENERIC_ERROR; + + webkit_glue::WebPlugin* webplugin = plugin->webplugin(); + if (!webplugin) + return NPERR_GENERIC_ERROR; + + std::string cookie(value, len); + GURL cookies_url((std::string(url))); + webplugin->SetCookie(cookies_url, cookies_url, cookie); + return NPERR_NO_ERROR; + } + case NPNURLVProxy: + // We don't support setting proxy values, fall through... + break; + default: + // Fall through and return an error... + break; + } + + return NPERR_GENERIC_ERROR; +} + +NPError NPN_GetAuthenticationInfo(NPP id, + const char* protocol, + const char* host, + int32_t port, + const char* scheme, + const char* realm, + char** username, + uint32_t* ulen, + char** password, + uint32_t* plen) { + if (!id || !protocol || !host || !scheme || !realm || !username || + !ulen || !password || !plen) + return NPERR_INVALID_PARAM; + + // TODO: implement me (bug 23928) + return NPERR_GENERIC_ERROR; +} + +uint32_t NPN_ScheduleTimer(NPP id, + uint32_t interval, + NPBool repeat, + void (*func)(NPP id, uint32_t timer_id)) { + scoped_refptr plugin(FindInstance(id)); + if (!plugin) + return 0; + + return plugin->ScheduleTimer(interval, repeat, func); +} + +void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) { + scoped_refptr plugin(FindInstance(id)); + if (plugin) + plugin->UnscheduleTimer(timer_id); +} + +NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) { + if (!menu) + return NPERR_INVALID_PARAM; + + scoped_refptr plugin(FindInstance(id)); + if (plugin.get()) { + return plugin->PopUpContextMenu(menu); + } + NOTREACHED(); + return NPERR_GENERIC_ERROR; +} + +NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY, + NPCoordinateSpace sourceSpace, + double *destX, double *destY, + NPCoordinateSpace destSpace) { + scoped_refptr plugin(FindInstance(id)); + if (plugin.get()) { + return plugin->ConvertPoint(sourceX, sourceY, sourceSpace, + destX, destY, destSpace); + } + NOTREACHED(); + return false; +} + +NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) { + // TODO: Implement advanced key handling: http://crbug.com/46578 + NOTIMPLEMENTED(); + return false; +} + +NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { + // TODO: Implement advanced key handling: http://crbug.com/46578 + NOTIMPLEMENTED(); + return false; +} + +void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { + scoped_refptr plugin(FindInstance(instance)); + if (plugin.get()) { + plugin->URLRedirectResponse(!!allow, notify_data); + } +} + +} // extern "C" diff --git a/webkit/glue/plugins/plugin_host.h b/webkit/glue/plugins/plugin_host.h new file mode 100644 index 0000000..4763df1 --- /dev/null +++ b/webkit/glue/plugins/plugin_host.h @@ -0,0 +1,63 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO: Need mechanism to cleanup the static instance + +#ifndef WEBKIT_GLUE_PLUGIN_PLUGIN_HOST_H__ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_HOST_H__ + +#include +#include + +#include "base/ref_counted.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +namespace NPAPI +{ +class PluginInstance; + +// The Plugin Host implements the NPN_xxx functions for NPAPI plugins. +// These are the functions exposed from the Plugin Host for use +// by the Plugin. +// +// The PluginHost is managed as a singleton. This isn't strictly +// necessary, but since the callback functions are all global C +// functions, there is really no point in having per-instance PluginHosts. +class PluginHost : public base::RefCounted { + public: + // Access the single PluginHost instance. Callers + // must call deref() when finished with the object. + static PluginHost *Singleton(); + + // The table of functions provided to the plugin. + NPNetscapeFuncs *host_functions() { return &host_funcs_; } + + // Helper function for parsing post headers, and applying attributes + // to the stream. NPAPI post data include headers + data combined. + // This function parses it out and adds it to the stream in a WebKit + // style. + static bool SetPostData(const char *buf, + uint32 length, + std::vector* names, + std::vector* values, + std::vector* body); + + void PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides); + + private: + friend class base::RefCounted; + + virtual ~PluginHost(); + + PluginHost(); + void InitializeHostFuncs(); + static scoped_refptr singleton_; + NPNetscapeFuncs host_funcs_; + DISALLOW_COPY_AND_ASSIGN(PluginHost); +}; + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_HOST_H__ diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc new file mode 100644 index 0000000..4ccbadf --- /dev/null +++ b/webkit/glue/plugins/plugin_instance.cc @@ -0,0 +1,680 @@ +// 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 "build/build_config.h" + +#include "webkit/glue/plugins/plugin_instance.h" + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/plugin_host.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/plugin_string_stream.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "net/base/escape.h" + +#if defined(OS_MACOSX) +#include +#endif + +namespace NPAPI { + +PluginInstance::PluginInstance(PluginLib *plugin, const std::string &mime_type) + : plugin_(plugin), + npp_(0), + host_(PluginHost::Singleton()), + npp_functions_(plugin->functions()), + window_handle_(0), + windowless_(false), + transparent_(true), + webplugin_(0), + mime_type_(mime_type), + use_mozilla_user_agent_(false), +#if defined (OS_MACOSX) +#ifdef NP_NO_QUICKDRAW + drawing_model_(NPDrawingModelCoreGraphics), +#else + drawing_model_(NPDrawingModelQuickDraw), +#endif +#ifdef NP_NO_CARBON + event_model_(NPEventModelCocoa), +#else + event_model_(NPEventModelCarbon), +#endif + currently_handled_event_(NULL), +#endif + message_loop_(MessageLoop::current()), + load_manually_(false), + in_close_streams_(false), + next_timer_id_(1), + next_notify_id_(0), + next_range_request_id_(0), + handles_url_redirects_(false) { + npp_ = new NPP_t(); + npp_->ndata = 0; + npp_->pdata = 0; + + memset(&zero_padding_, 0, sizeof(zero_padding_)); + DCHECK(message_loop_); +} + +PluginInstance::~PluginInstance() { + CloseStreams(); + + if (npp_ != 0) { + delete npp_; + npp_ = 0; + } + + if (plugin_) + plugin_->CloseInstance(); +} + +PluginStreamUrl* PluginInstance::CreateStream(unsigned long resource_id, + const GURL& url, + const std::string& mime_type, + int notify_id) { + + bool notify; + void* notify_data; + GetNotifyData(notify_id, ¬ify, ¬ify_data); + PluginStreamUrl* stream = new PluginStreamUrl( + resource_id, url, this, notify, notify_data); + + AddStream(stream); + return stream; +} + +void PluginInstance::AddStream(PluginStream* stream) { + open_streams_.push_back(make_scoped_refptr(stream)); +} + +void PluginInstance::RemoveStream(PluginStream* stream) { + if (in_close_streams_) + return; + + std::vector >::iterator stream_index; + for (stream_index = open_streams_.begin(); + stream_index != open_streams_.end(); ++stream_index) { + if (*stream_index == stream) { + open_streams_.erase(stream_index); + break; + } + } +} + +bool PluginInstance::IsValidStream(const NPStream* stream) { + std::vector >::iterator stream_index; + for (stream_index = open_streams_.begin(); + stream_index != open_streams_.end(); ++stream_index) { + if ((*stream_index)->stream() == stream) + return true; + } + + return false; +} + +void PluginInstance::CloseStreams() { + in_close_streams_ = true; + for (unsigned int index = 0; index < open_streams_.size(); ++index) { + // Close all streams on the way down. + open_streams_[index]->Close(NPRES_USER_BREAK); + } + open_streams_.clear(); + in_close_streams_ = false; +} + +webkit_glue::WebPluginResourceClient* PluginInstance::GetRangeRequest( + int id) { + PendingRangeRequestMap::iterator iter = pending_range_requests_.find(id); + if (iter == pending_range_requests_.end()) { + NOTREACHED(); + return NULL; + } + + webkit_glue::WebPluginResourceClient* rv = iter->second->AsResourceClient(); + pending_range_requests_.erase(iter); + return rv; +} + +bool PluginInstance::Start(const GURL& url, + char** const param_names, + char** const param_values, + int param_count, + bool load_manually) { + load_manually_ = load_manually; + unsigned short mode = load_manually_ ? NP_FULL : NP_EMBED; + npp_->ndata = this; + + NPError err = NPP_New(mode, param_count, + const_cast(param_names), const_cast(param_values)); + + if (err == NPERR_NO_ERROR) { + handles_url_redirects_ = + ((npp_functions_->version >= NPVERS_HAS_URL_REDIRECT_HANDLING) && + (npp_functions_->urlredirectnotify)); + } + return err == NPERR_NO_ERROR; +} + +NPObject *PluginInstance::GetPluginScriptableObject() { + NPObject *value = NULL; + NPError error = NPP_GetValue(NPPVpluginScriptableNPObject, &value); + if (error != NPERR_NO_ERROR || value == NULL) + return NULL; + return value; +} + +// WebPluginLoadDelegate methods +void PluginInstance::DidFinishLoadWithReason( + const GURL& url, NPReason reason, int notify_id) { + bool notify; + void* notify_data; + GetNotifyData(notify_id, ¬ify, ¬ify_data); + if (!notify) { + NOTREACHED(); + return; + } + + NPP_URLNotify(url.spec().c_str(), reason, notify_data); +} + +unsigned PluginInstance::GetBackingTextureId() { + // By default the plugin instance is not backed by an OpenGL texture. + return 0; +} + +// NPAPI methods +NPError PluginInstance::NPP_New(unsigned short mode, + short argc, + char *argn[], + char *argv[]) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->newp != 0); + DCHECK(argc >= 0); + + if (npp_functions_->newp != 0) { + return npp_functions_->newp( + (NPMIMEType)mime_type_.c_str(), npp_, mode, argc, argn, argv, NULL); + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +void PluginInstance::NPP_Destroy() { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->destroy != 0); + + if (npp_functions_->destroy != 0) { + NPSavedData *savedData = 0; + npp_functions_->destroy(npp_, &savedData); + + // TODO: Support savedData. Technically, these need to be + // saved on a per-URL basis, and then only passed + // to new instances of the plugin at the same URL. + // Sounds like a huge security risk. When we do support + // these, we should pass them back to the PluginLib + // to be stored there. + DCHECK(savedData == 0); + } + + for (unsigned int file_index = 0; file_index < files_created_.size(); + file_index++) { + file_util::Delete(files_created_[file_index], false); + } + + // Ensure that no timer callbacks are invoked after NPP_Destroy. + timers_.clear(); +} + +NPError PluginInstance::NPP_SetWindow(NPWindow *window) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->setwindow != 0); + + if (npp_functions_->setwindow != 0) { + return npp_functions_->setwindow(npp_, window); + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +NPError PluginInstance::NPP_NewStream(NPMIMEType type, + NPStream *stream, + NPBool seekable, + unsigned short *stype) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->newstream != 0); + if (npp_functions_->newstream != 0) { + return npp_functions_->newstream(npp_, type, stream, seekable, stype); + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +NPError PluginInstance::NPP_DestroyStream(NPStream *stream, NPReason reason) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->destroystream != 0); + + if (stream == NULL || !IsValidStream(stream) || (stream->ndata == NULL)) + return NPERR_INVALID_INSTANCE_ERROR; + + if (npp_functions_->destroystream != 0) { + NPError result = npp_functions_->destroystream(npp_, stream, reason); + stream->ndata = NULL; + return result; + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +int PluginInstance::NPP_WriteReady(NPStream *stream) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->writeready != 0); + if (npp_functions_->writeready != 0) { + return npp_functions_->writeready(npp_, stream); + } + return 0; +} + +int PluginInstance::NPP_Write(NPStream *stream, + int offset, + int len, + void *buffer) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->write != 0); + if (npp_functions_->write != 0) { + return npp_functions_->write(npp_, stream, offset, len, buffer); + } + return 0; +} + +void PluginInstance::NPP_StreamAsFile(NPStream *stream, const char *fname) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->asfile != 0); + if (npp_functions_->asfile != 0) { + npp_functions_->asfile(npp_, stream, fname); + } + + // Creating a temporary FilePath instance on the stack as the explicit + // FilePath constructor with StringType as an argument causes a compiler + // error when invoked via vector push back. + FilePath file_name = FilePath::FromWStringHack(UTF8ToWide(fname)); + files_created_.push_back(file_name); +} + +void PluginInstance::NPP_URLNotify(const char *url, + NPReason reason, + void *notifyData) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->urlnotify != 0); + if (npp_functions_->urlnotify != 0) { + npp_functions_->urlnotify(npp_, url, reason, notifyData); + } +} + +NPError PluginInstance::NPP_GetValue(NPPVariable variable, void *value) { + DCHECK(npp_functions_ != 0); + // getvalue is NULL for Shockwave + if (npp_functions_->getvalue != 0) { + return npp_functions_->getvalue(npp_, variable, value); + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +NPError PluginInstance::NPP_SetValue(NPNVariable variable, void *value) { + DCHECK(npp_functions_ != 0); + if (npp_functions_->setvalue != 0) { + return npp_functions_->setvalue(npp_, variable, value); + } + return NPERR_INVALID_FUNCTABLE_ERROR; +} + +short PluginInstance::NPP_HandleEvent(void* event) { + DCHECK(npp_functions_ != 0); + DCHECK(npp_functions_->event != 0); + if (npp_functions_->event != 0) { + return npp_functions_->event(npp_, (void*)event); + } + return false; +} + +bool PluginInstance::NPP_Print(NPPrint* platform_print) { + DCHECK(npp_functions_ != 0); + if (npp_functions_->print != 0) { + npp_functions_->print(npp_, platform_print); + return true; + } + return false; +} + +NPError PluginInstance::NPP_ClearSiteData(uint64 flags, + const char* domain, + uint64 max_age) { + DCHECK(npp_functions_ != 0); + // TODO(bauerb): Call NPAPI function when it is defined in the header. + return NPERR_NO_ERROR; +} + +void PluginInstance::NPP_URLRedirectNotify(const char* url, int32_t status, + void* notify_data) { + DCHECK(npp_functions_ != 0); + if (npp_functions_->urlredirectnotify != 0) { + npp_functions_->urlredirectnotify(npp_, url, status, notify_data); + } +} + +void PluginInstance::SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id) { + bool notify; + void* notify_data; + GetNotifyData(notify_id, ¬ify, ¬ify_data); + + if (success) { + PluginStringStream *stream = + new PluginStringStream(this, url, notify, notify_data); + AddStream(stream); + stream->SendToPlugin(result, "text/html"); + } else { + // NOTE: Sending an empty stream here will crash MacroMedia + // Flash 9. Just send the URL Notify. + if (notify) + NPP_URLNotify(url.spec().c_str(), NPRES_DONE, notify_data); + } +} + +void PluginInstance::DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified) { + DCHECK(load_manually_); + + plugin_data_stream_ = CreateStream(-1, url, mime_type, 0); + plugin_data_stream_->DidReceiveResponse(mime_type, headers, expected_length, + last_modified, true); +} + +void PluginInstance::DidReceiveManualData(const char* buffer, int length) { + DCHECK(load_manually_); + if (plugin_data_stream_.get() != NULL) { + plugin_data_stream_->DidReceiveData(buffer, length, 0); + } +} + +void PluginInstance::DidFinishManualLoading() { + DCHECK(load_manually_); + if (plugin_data_stream_.get() != NULL) { + plugin_data_stream_->DidFinishLoading(); + plugin_data_stream_->Close(NPRES_DONE); + plugin_data_stream_ = NULL; + } +} + +void PluginInstance::DidManualLoadFail() { + DCHECK(load_manually_); + if (plugin_data_stream_.get() != NULL) { + plugin_data_stream_->DidFail(); + plugin_data_stream_ = NULL; + } +} + +void PluginInstance::PluginThreadAsyncCall(void (*func)(void *), + void *user_data) { + message_loop_->PostTask( + FROM_HERE, NewRunnableMethod( + this, &PluginInstance::OnPluginThreadAsyncCall, func, user_data)); +} + +void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void *), + void *user_data) { + // Do not invoke the callback if NPP_Destroy has already been invoked. + if (webplugin_) + func(user_data); +} + +uint32 PluginInstance::ScheduleTimer(uint32 interval, + NPBool repeat, + void (*func)(NPP id, uint32 timer_id)) { + // Use next timer id. + uint32 timer_id; + timer_id = next_timer_id_; + ++next_timer_id_; + DCHECK(next_timer_id_ != 0); + + // Record timer interval and repeat. + TimerInfo info; + info.interval = interval; + info.repeat = repeat ? true : false; + timers_[timer_id] = info; + + // Schedule the callback. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + NewRunnableMethod( + this, &PluginInstance::OnTimerCall, func, npp_, timer_id), + interval); + return timer_id; +} + +void PluginInstance::UnscheduleTimer(uint32 timer_id) { + // Remove info about the timer. + TimerMap::iterator it = timers_.find(timer_id); + if (it != timers_.end()) + timers_.erase(it); +} + +#if !defined(OS_MACOSX) +NPError PluginInstance::PopUpContextMenu(NPMenu* menu) { + NOTIMPLEMENTED(); + return NPERR_GENERIC_ERROR; +} +#endif + +void PluginInstance::OnTimerCall(void (*func)(NPP id, uint32 timer_id), + NPP id, + uint32 timer_id) { + // Do not invoke callback if the timer has been unscheduled. + TimerMap::iterator it = timers_.find(timer_id); + if (it == timers_.end()) + return; + + // Get all information about the timer before invoking the callback. The + // callback might unschedule the timer. + TimerInfo info = it->second; + + func(id, timer_id); + + // If the timer was unscheduled by the callback, just free up the timer id. + if (timers_.find(timer_id) == timers_.end()) + return; + + // Reschedule repeating timers after invoking the callback so callback is not + // re-entered if it pumps the messager loop. + if (info.repeat) { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + NewRunnableMethod( + this, &PluginInstance::OnTimerCall, func, npp_, timer_id), + info.interval); + } else { + timers_.erase(it); + } +} + +void PluginInstance::PushPopupsEnabledState(bool enabled) { + popups_enabled_stack_.push(enabled); +} + +void PluginInstance::PopPopupsEnabledState() { + popups_enabled_stack_.pop(); +} + +void PluginInstance::RequestRead(NPStream* stream, NPByteRange* range_list) { + std::string range_info = "bytes="; + + while (range_list) { + range_info += base::IntToString(range_list->offset); + range_info.push_back('-'); + range_info += + base::IntToString(range_list->offset + range_list->length - 1); + range_list = range_list->next; + if (range_list) + range_info.push_back(','); + } + + if (plugin_data_stream_) { + if (plugin_data_stream_->stream() == stream) { + webplugin_->CancelDocumentLoad(); + plugin_data_stream_ = NULL; + } + } + + // The lifetime of a NPStream instance depends on the PluginStream instance + // which owns it. When a plugin invokes NPN_RequestRead on a seekable stream, + // we don't want to create a new stream when the corresponding response is + // received. We send over a cookie which represents the PluginStream + // instance which is sent back from the renderer when the response is + // received. + std::vector >::iterator stream_index; + for (stream_index = open_streams_.begin(); + stream_index != open_streams_.end(); ++stream_index) { + PluginStream* plugin_stream = *stream_index; + if (plugin_stream->stream() == stream) { + // A stream becomes seekable the first time NPN_RequestRead + // is called on it. + plugin_stream->set_seekable(true); + + pending_range_requests_[++next_range_request_id_] = plugin_stream; + webplugin_->InitiateHTTPRangeRequest( + stream->url, range_info.c_str(), next_range_request_id_); + return; + } + } + NOTREACHED(); +} + +void PluginInstance::RequestURL(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + bool notify, + void* notify_data) { + int notify_id = 0; + if (notify) { + notify_id = ++next_notify_id_; + pending_requests_[notify_id] = notify_data; + } + + webplugin_->HandleURLRequest( + url, method, target, buf, len, notify_id, popups_allowed(), + notify ? handles_url_redirects_ : false); +} + +bool PluginInstance::ConvertPoint(double source_x, double source_y, + NPCoordinateSpace source_space, + double* dest_x, double* dest_y, + NPCoordinateSpace dest_space) { +#if defined(OS_MACOSX) + CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID()); + + double flipped_screen_x = source_x; + double flipped_screen_y = source_y; + switch(source_space) { + case NPCoordinateSpacePlugin: + flipped_screen_x += plugin_origin_.x(); + flipped_screen_y += plugin_origin_.y(); + break; + case NPCoordinateSpaceWindow: + flipped_screen_x += containing_window_frame_.x(); + flipped_screen_y = containing_window_frame_.height() - source_y + + containing_window_frame_.y(); + break; + case NPCoordinateSpaceFlippedWindow: + flipped_screen_x += containing_window_frame_.x(); + flipped_screen_y += containing_window_frame_.y(); + break; + case NPCoordinateSpaceScreen: + flipped_screen_y = main_display_bounds.size.height - flipped_screen_y; + break; + case NPCoordinateSpaceFlippedScreen: + break; + default: + NOTREACHED(); + return false; + } + + double target_x = flipped_screen_x; + double target_y = flipped_screen_y; + switch(dest_space) { + case NPCoordinateSpacePlugin: + target_x -= plugin_origin_.x(); + target_y -= plugin_origin_.y(); + break; + case NPCoordinateSpaceWindow: + target_x -= containing_window_frame_.x(); + target_y -= containing_window_frame_.y(); + target_y = containing_window_frame_.height() - target_y; + break; + case NPCoordinateSpaceFlippedWindow: + target_x -= containing_window_frame_.x(); + target_y -= containing_window_frame_.y(); + break; + case NPCoordinateSpaceScreen: + target_y = main_display_bounds.size.height - flipped_screen_y; + break; + case NPCoordinateSpaceFlippedScreen: + break; + default: + NOTREACHED(); + return false; + } + + if (dest_x) + *dest_x = target_x; + if (dest_y) + *dest_y = target_y; + return true; +#else + NOTIMPLEMENTED(); + return false; +#endif +} + +void PluginInstance::GetNotifyData( + int notify_id, bool* notify, void** notify_data) { + PendingRequestMap::iterator iter = pending_requests_.find(notify_id); + if (iter != pending_requests_.end()) { + *notify = true; + *notify_data = iter->second; + pending_requests_.erase(iter); + } else { + *notify = false; + *notify_data = NULL; + } +} + +void PluginInstance::URLRedirectResponse(bool allow, void* notify_data) { + // The notify_data passed in allows us to identify the matching stream. + std::vector >::iterator stream_index; + for (stream_index = open_streams_.begin(); + stream_index != open_streams_.end(); ++stream_index) { + PluginStream* plugin_stream = *stream_index; + if (plugin_stream->notify_data() == notify_data) { + webkit_glue::WebPluginResourceClient* resource_client = + plugin_stream->AsResourceClient(); + webplugin_->URLRedirectResponse(allow, resource_client->ResourceId()); + if (allow) { + plugin_stream->UpdateUrl( + plugin_stream->pending_redirect_url().c_str()); + } + break; + } + } +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h new file mode 100644 index 0000000..fa0320e --- /dev/null +++ b/webkit/glue/plugins/plugin_instance.h @@ -0,0 +1,375 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO: Need to deal with NPAPI's NPSavedData. +// I haven't seen plugins use it yet. + +#ifndef WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ + +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "gfx/native_widget_types.h" +#include "gfx/point.h" +#include "gfx/rect.h" +#include "googleurl/src/gurl.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +class MessageLoop; + +namespace webkit_glue { +class WebPlugin; +class WebPluginResourceClient; +} + +namespace NPAPI +{ +class PluginLib; +class PluginHost; +class PluginStream; +class PluginStreamUrl; +class PluginDataStream; +#if defined(OS_MACOSX) +class ScopedCurrentPluginEvent; +#endif + +// A PluginInstance is an active, running instance of a Plugin. +// A single plugin may have many PluginInstances. +class PluginInstance : public base::RefCountedThreadSafe { + public: + // Create a new instance of a plugin. The PluginInstance + // will hold a reference to the plugin. + PluginInstance(PluginLib *plugin, const std::string &mime_type); + + // Activates the instance by calling NPP_New. + // This should be called after our instance is all + // setup from the host side and we are ready to receive + // requests from the plugin. We must not call any + // functions on the plugin instance until start has + // been called. + // + // url: The instance URL. + // param_names: the list of names of attributes passed via the + // element. + // param_values: the list of values corresponding to param_names + // param_count: number of attributes + // load_manually: if true indicates that the plugin data would be passed + // from webkit. if false indicates that the plugin should + // download the data. + // This also controls whether the plugin is instantiated as + // a full page plugin (NP_FULL) or embedded (NP_EMBED) + // + bool Start(const GURL& url, + char** const param_names, + char** const param_values, + int param_count, + bool load_manually); + + // NPAPI's instance identifier for this instance + NPP npp() { return npp_; } + + // Get/Set for the instance's window handle. + gfx::PluginWindowHandle window_handle() const { return window_handle_; } + void set_window_handle(gfx::PluginWindowHandle value) { + window_handle_ = value; + } + + // Get/Set whether this instance is in Windowless mode. + // Default is false. + bool windowless() { return windowless_; } + void set_windowless(bool value) { windowless_ = value; } + + // Get/Set whether this instance is transparent. + // This only applies to windowless plugins. Transparent + // plugins require that webkit paint the background. + // Default is true. + bool transparent() { return transparent_; } + void set_transparent(bool value) { transparent_ = value; } + + // Get/Set the WebPlugin associated with this instance + webkit_glue::WebPlugin* webplugin() { return webplugin_; } + void set_web_plugin(webkit_glue::WebPlugin* webplugin) { + webplugin_ = webplugin; + } + + // Get the mimeType for this plugin stream + const std::string &mime_type() { return mime_type_; } + + NPAPI::PluginLib* plugin_lib() { return plugin_; } + +#if defined(OS_MACOSX) + // Get/Set the Mac NPAPI drawing and event models + NPDrawingModel drawing_model() { return drawing_model_; } + void set_drawing_model(NPDrawingModel value) { drawing_model_ = value; } + NPEventModel event_model() { return event_model_; } + void set_event_model(NPEventModel value) { event_model_ = value; } + // Updates the instance's tracking of the location of the plugin location + // relative to the upper left of the screen. + void set_plugin_origin(const gfx::Point& origin) { plugin_origin_ = origin; } + // Updates the instance's tracking of the frame of the containing window + // relative to the upper left of the screen. + void set_window_frame(const gfx::Rect& frame) { + containing_window_frame_ = frame; + } +#endif + + // Creates a stream for sending an URL. If notify_id is non-zero, it will + // send a notification to the plugin when the stream is complete; otherwise it + // will not. Set object_url to true if the load is for the object tag's url, + // or false if it's for a url that the plugin fetched through + // NPN_GetUrl[Notify]. + PluginStreamUrl* CreateStream(unsigned long resource_id, + const GURL& url, + const std::string& mime_type, + int notify_id); + + // For each instance, we track all streams. When the + // instance closes, all remaining streams are also + // closed. All streams associated with this instance + // should call AddStream so that they can be cleaned + // up when the instance shuts down. + void AddStream(PluginStream* stream); + + // This is called when a stream is closed. We remove the stream from the + // list, which releases the reference maintained to the stream. + void RemoveStream(PluginStream* stream); + + // Closes all open streams on this instance. + void CloseStreams(); + + // Returns the WebPluginResourceClient object for a stream that has become + // seekable. + webkit_glue::WebPluginResourceClient* GetRangeRequest(int id); + + // Have the plugin create it's script object. + NPObject *GetPluginScriptableObject(); + + // WebViewDelegate methods that we implement. This is for handling + // callbacks during getURLNotify. + void DidFinishLoadWithReason(const GURL& url, NPReason reason, int notify_id); + + // If true, send the Mozilla user agent instead of Chrome's to the plugin. + bool use_mozilla_user_agent() { return use_mozilla_user_agent_; } + void set_use_mozilla_user_agent() { use_mozilla_user_agent_ = true; } + + // If the plugin instance is backed by a texture, return its ID in the + // compositor's namespace. Otherwise return 0. Returns 0 by default. + virtual unsigned GetBackingTextureId(); + + // Helper that implements NPN_PluginThreadAsyncCall semantics + void PluginThreadAsyncCall(void (*func)(void *), + void *userData); + + uint32 ScheduleTimer(uint32 interval, + NPBool repeat, + void (*func)(NPP id, uint32 timer_id)); + + void UnscheduleTimer(uint32 timer_id); + + bool ConvertPoint(double source_x, double source_y, + NPCoordinateSpace source_space, + double* dest_x, double* dest_y, + NPCoordinateSpace dest_space); + + NPError PopUpContextMenu(NPMenu* menu); + + // + // NPAPI methods for calling the Plugin Instance + // + NPError NPP_New(unsigned short, short, char *[], char *[]); + NPError NPP_SetWindow(NPWindow *); + NPError NPP_NewStream(NPMIMEType, NPStream *, NPBool, unsigned short *); + NPError NPP_DestroyStream(NPStream *, NPReason); + int NPP_WriteReady(NPStream *); + int NPP_Write(NPStream *, int, int, void *); + void NPP_StreamAsFile(NPStream *, const char *); + void NPP_URLNotify(const char *, NPReason, void *); + NPError NPP_GetValue(NPPVariable, void *); + NPError NPP_SetValue(NPNVariable, void *); + short NPP_HandleEvent(void*); + void NPP_Destroy(); + bool NPP_Print(NPPrint* platform_print); + NPError NPP_ClearSiteData(uint64, const char*, uint64); + void NPP_URLRedirectNotify(const char* url, int32_t status, + void* notify_data); + + void SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id); + + void DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified); + void DidReceiveManualData(const char* buffer, int length); + void DidFinishManualLoading(); + void DidManualLoadFail(); + + void PushPopupsEnabledState(bool enabled); + void PopPopupsEnabledState(); + + bool popups_allowed() const { + return popups_enabled_stack_.empty() ? false : popups_enabled_stack_.top(); + } + + // Initiates byte range reads for plugins. + void RequestRead(NPStream* stream, NPByteRange* range_list); + + // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated + // by plugins. + void RequestURL(const char* url, + const char* method, + const char* target, + const char* buf, + unsigned int len, + bool notify, + void* notify_data); + + // Handles NPN_URLRedirectResponse calls issued by plugins in response to + // HTTP URL redirect notifications. + void URLRedirectResponse(bool allow, void* notify_data); + + bool handles_url_redirects() const { return handles_url_redirects_; } + + private: + friend class base::RefCountedThreadSafe; + +#if defined(OS_MACOSX) + friend class ScopedCurrentPluginEvent; + // Sets the event that the plugin is currently handling. The object is not + // owned or copied, so the caller must call this again with NULL before the + // event pointer becomes invalid. Clients use ScopedCurrentPluginEvent rather + // than calling this directly. + void set_currently_handled_event(NPCocoaEvent* event) { + currently_handled_event_ = event; + } +#endif + + ~PluginInstance(); + void OnPluginThreadAsyncCall(void (*func)(void *), void *userData); + void OnTimerCall(void (*func)(NPP id, uint32 timer_id), + NPP id, uint32 timer_id); + bool IsValidStream(const NPStream* stream); + void GetNotifyData(int notify_id, bool* notify, void** notify_data); + + // This is a hack to get the real player plugin to work with chrome + // The real player plugin dll(nppl3260) when loaded by firefox is loaded via + // the NS COM API which is analogous to win32 COM. So the NPAPI functions in + // the plugin are invoked via an interface by firefox. The plugin instance + // handle which is passed to every NPAPI method is owned by the real player + // plugin, i.e. it expects the ndata member to point to a structure which + // it knows about. Eventually it dereferences this structure and compares + // a member variable at offset 0x24(Version 6.0.11.2888) /2D (Version + // 6.0.11.3088) with 0 and on failing this check, takes a different code + // path which causes a crash. Safari and Opera work with version 6.0.11.2888 + // by chance as their ndata structure contains a 0 at the location which real + // player checks:(. They crash with version 6.0.11.3088 as well. The + // following member just adds a 96 byte padding to our PluginInstance class + // which is passed in the ndata member. This magic number works correctly on + // Vista with UAC on or off :(. + // NOTE: Please dont change the ordering of the member variables + // New members should be added after this padding array. + // TODO(iyengar) : Disassemble the Realplayer ndata structure and look into + // the possiblity of conforming to it (http://b/issue?id=936667). We + // could also log a bug with Real, which would save the effort. + uint8 zero_padding_[96]; + scoped_refptr plugin_; + NPP npp_; + scoped_refptr host_; + NPPluginFuncs* npp_functions_; + std::vector > open_streams_; + gfx::PluginWindowHandle window_handle_; + bool windowless_; + bool transparent_; + webkit_glue::WebPlugin* webplugin_; + std::string mime_type_; + GURL get_url_; + intptr_t get_notify_data_; + bool use_mozilla_user_agent_; +#if defined(OS_MACOSX) + NPDrawingModel drawing_model_; + NPEventModel event_model_; + gfx::Point plugin_origin_; + gfx::Rect containing_window_frame_; + NPCocoaEvent* currently_handled_event_; // weak +#endif + MessageLoop* message_loop_; + scoped_refptr plugin_data_stream_; + + // This flag if true indicates that the plugin data would be passed from + // webkit. if false indicates that the plugin should download the data. + bool load_manually_; + + // Stack indicating if popups are to be enabled for the outgoing + // NPN_GetURL/NPN_GetURLNotify calls. + std::stack popups_enabled_stack_; + + // True if in CloseStreams(). + bool in_close_streams_; + + // List of files created for the current plugin instance. File names are + // added to the list every time the NPP_StreamAsFile function is called. + std::vector files_created_; + + // Next unusued timer id. + uint32 next_timer_id_; + + // Map of timer id to settings for timer. + struct TimerInfo { + uint32 interval; + bool repeat; + }; + typedef std::map TimerMap; + TimerMap timers_; + + // Tracks pending GET/POST requests so that the plugin-given data doesn't + // cross process boundaries to an untrusted process. + typedef std::map PendingRequestMap; + PendingRequestMap pending_requests_; + int next_notify_id_; + + // Used to track pending range requests so that when WebPlugin replies to us + // we can match the reply to the stream. + typedef std::map > PendingRangeRequestMap; + PendingRangeRequestMap pending_range_requests_; + int next_range_request_id_; + // The plugin handles the NPAPI URL redirect notification API. + // See here https://wiki.mozilla.org/NPAPI:HTTPRedirectHandling + bool handles_url_redirects_; + + DISALLOW_COPY_AND_ASSIGN(PluginInstance); +}; + +#if defined(OS_MACOSX) +// Helper to simplify correct usage of set_currently_handled_event. +// Instantiating will set |instance|'s currently handled to |event| for the +// lifetime of the object, then NULL when it goes out of scope. +class ScopedCurrentPluginEvent { + public: + ScopedCurrentPluginEvent(PluginInstance* instance, NPCocoaEvent* event) + : instance_(instance) { + instance_->set_currently_handled_event(event); + } + ~ScopedCurrentPluginEvent() { + instance_->set_currently_handled_event(NULL); + } + private: + scoped_refptr instance_; + DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent); +}; +#endif + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ diff --git a/webkit/glue/plugins/plugin_instance_mac.mm b/webkit/glue/plugins/plugin_instance_mac.mm new file mode 100644 index 0000000..9800198 --- /dev/null +++ b/webkit/glue/plugins/plugin_instance_mac.mm @@ -0,0 +1,133 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "build/build_config.h" + +#import + +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_instance.h" + +// When C++ exceptions are disabled, the C++ library defines |try| and +// |catch| so as to allow exception-expecting C++ code to build properly when +// language support for exceptions is not present. These macros interfere +// with the use of |@try| and |@catch| in Objective-C files such as this one. +// Undefine these macros here, after everything has been #included, since +// there will be no C++ uses and only Objective-C uses from this point on. +#undef try +#undef catch + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 +@interface NSMenu (SnowLeopardMenuPopUpDeclaration) +- (BOOL)popUpMenuPositioningItem:(NSMenuItem*)item + atLocation:(NSPoint)location + inView:(NSView*)view; +@end +#endif + +namespace { + +// Returns an autoreleased NSEvent constructed from the given np_event, +// targeting the given window. +NSEvent* NSEventForNPCocoaEvent(NPCocoaEvent* np_event, NSWindow* window) { + bool mouse_down = 1; + switch (np_event->type) { + case NPCocoaEventMouseDown: + mouse_down = 1; + break; + case NPCocoaEventMouseUp: + mouse_down = 0; + break; + default: + // If plugins start bringing up context menus for things other than + // clicks, this will need more plumbing; for now just log it and proceed + // as if it were a mouse down. + NOTREACHED(); + } + NSEventType event_type = NSLeftMouseDown; + switch (np_event->data.mouse.buttonNumber) { + case 0: + event_type = mouse_down ? NSLeftMouseDown : NSLeftMouseUp; + break; + case 1: + event_type = mouse_down ? NSRightMouseDown : NSRightMouseUp; + break; + default: + event_type = mouse_down ? NSOtherMouseDown : NSOtherMouseUp; + break; + } + + NSInteger click_count = np_event->data.mouse.clickCount; + NSInteger modifiers = np_event->data.mouse.modifierFlags; + // NPCocoaEvent doesn't have a timestamp, so just use the current time. + NSEvent* event = + [NSEvent mouseEventWithType:event_type + location:NSMakePoint(0, 0) + modifierFlags:modifiers + timestamp:[[NSApp currentEvent] timestamp] + windowNumber:[window windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:0 + clickCount:click_count + pressure:1.0]; + return event; +} + +} // namespace + +namespace NPAPI { + +NPError PluginInstance::PopUpContextMenu(NPMenu* menu) { + if (!currently_handled_event_) + return NPERR_GENERIC_ERROR; + + CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID()); + NSPoint screen_point = NSMakePoint( + plugin_origin_.x() + currently_handled_event_->data.mouse.pluginX, + plugin_origin_.y() + currently_handled_event_->data.mouse.pluginY); + // Plugin offsets are upper-left based, so flip vertically for Cocoa. + screen_point.y = main_display_bounds.size.height - screen_point.y; + + NSMenu* nsmenu = reinterpret_cast(menu); + NPError return_val = NPERR_NO_ERROR; + NSWindow* window = nil; + @try { + if ([nsmenu respondsToSelector: + @selector(popUpMenuPositioningItem:atLocation:inView:)]) { + [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil]; + } else { + NSRect dummy_window_rect = NSMakeRect(screen_point.x, screen_point.y, + 1, 1); + window = [[NSWindow alloc] initWithContentRect:dummy_window_rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreNonretained + defer:YES]; + [window setTitle:@"PopupMenuDummy"]; // Lets interposing identify it. + [window setAlphaValue:0]; + [window makeKeyAndOrderFront:nil]; + [NSMenu popUpContextMenu:nsmenu + withEvent:NSEventForNPCocoaEvent(currently_handled_event_, + window) + forView:[window contentView]]; + } + } + @catch (NSException* e) { + NSLog(@"Caught exception while handling PopUpContextMenu: %@", e); + return_val = NPERR_GENERIC_ERROR; + } + + if (window) { + @try { + [window orderOut:nil]; + [window release]; + } + @catch (NSException* e) { + NSLog(@"Caught exception while cleaning up in PopUpContextMenu: %@", e); + } + } + + return return_val; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_lib.cc b/webkit/glue/plugins/plugin_lib.cc new file mode 100644 index 0000000..4ae4da4 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib.cc @@ -0,0 +1,349 @@ +// 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 "webkit/glue/plugins/plugin_lib.h" + +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/metrics/stats_counters.h" +#include "base/string_util.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_host.h" +#include "webkit/glue/plugins/plugin_list.h" + +namespace NPAPI { + +const char kPluginLibrariesLoadedCounter[] = "PluginLibrariesLoaded"; +const char kPluginInstancesActiveCounter[] = "PluginInstancesActive"; + +// A list of all the instantiated plugins. +static std::vector >* g_loaded_libs; + +PluginLib* PluginLib::CreatePluginLib(const FilePath& filename) { + // We can only have one PluginLib object per plugin as it controls the per + // instance function calls (i.e. NP_Initialize and NP_Shutdown). So we keep + // a map of PluginLib objects. + if (!g_loaded_libs) + g_loaded_libs = new std::vector >; + + for (size_t i = 0; i < g_loaded_libs->size(); ++i) { + if ((*g_loaded_libs)[i]->plugin_info().path == filename) + return (*g_loaded_libs)[i]; + } + + WebPluginInfo info; + const PluginEntryPoints* entry_points = NULL; + if (!PluginList::Singleton()->ReadPluginInfo(filename, &info, &entry_points)) + return NULL; + + return new PluginLib(info, entry_points); +} + +void PluginLib::UnloadAllPlugins() { + if (g_loaded_libs) { + // PluginLib::Unload() can remove items from the list and even delete + // the list when it removes the last item, so we must work with a copy + // of the list so that we don't get the carpet removed under our feet. + std::vector > loaded_libs(*g_loaded_libs); + for (size_t i = 0; i < loaded_libs.size(); ++i) + loaded_libs[i]->Unload(); + + if (g_loaded_libs && g_loaded_libs->empty()) { + delete g_loaded_libs; + g_loaded_libs = NULL; + } + } +} + +void PluginLib::ShutdownAllPlugins() { + if (g_loaded_libs) { + for (size_t i = 0; i < g_loaded_libs->size(); ++i) + (*g_loaded_libs)[i]->Shutdown(); + } +} + +PluginLib::PluginLib(const WebPluginInfo& info, + const PluginEntryPoints* entry_points) + : web_plugin_info_(info), + library_(NULL), + initialized_(false), + saved_data_(0), + instance_count_(0), + skip_unload_(false) { + base::StatsCounter(kPluginLibrariesLoadedCounter).Increment(); + memset(static_cast(&plugin_funcs_), 0, sizeof(plugin_funcs_)); + g_loaded_libs->push_back(make_scoped_refptr(this)); + + if (entry_points) { + internal_ = true; + entry_points_ = *entry_points; + } else { + internal_ = false; + // We will read the entry points from the plugin directly. + memset(&entry_points_, 0, sizeof(entry_points_)); + } +} + +PluginLib::~PluginLib() { + base::StatsCounter(kPluginLibrariesLoadedCounter).Decrement(); + if (saved_data_ != 0) { + // TODO - delete the savedData object here + } +} + +NPPluginFuncs* PluginLib::functions() { + return &plugin_funcs_; +} + +NPError PluginLib::NP_Initialize() { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() + << "): initialized=" << initialized_; + if (initialized_) + return NPERR_NO_ERROR; + + if (!Load()) + return NPERR_MODULE_LOAD_FAILED_ERROR; + + PluginHost* host = PluginHost::Singleton(); + if (host == 0) + return NPERR_GENERIC_ERROR; + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + NPError rv = entry_points_.np_initialize(host->host_functions(), + &plugin_funcs_); +#else + NPError rv = entry_points_.np_initialize(host->host_functions()); +#if defined(OS_MACOSX) + // On the Mac, we need to get entry points after calling np_initialize to + // match the behavior of other browsers. + if (rv == NPERR_NO_ERROR) { + rv = entry_points_.np_getentrypoints(&plugin_funcs_); + } +#endif // OS_MACOSX +#endif + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value() + << "): result=" << rv; + initialized_ = (rv == NPERR_NO_ERROR); + return rv; +} + +void PluginLib::NP_Shutdown(void) { + DCHECK(initialized_); + entry_points_.np_shutdown(); +} + +void PluginLib::PreventLibraryUnload() { + skip_unload_ = true; +} + +PluginInstance* PluginLib::CreateInstance(const std::string& mime_type) { + PluginInstance* new_instance = new PluginInstance(this, mime_type); + instance_count_++; + base::StatsCounter(kPluginInstancesActiveCounter).Increment(); + DCHECK_NE(static_cast(NULL), new_instance); + return new_instance; +} + +void PluginLib::CloseInstance() { + base::StatsCounter(kPluginInstancesActiveCounter).Decrement(); + instance_count_--; + // If a plugin is running in its own process it will get unloaded on process + // shutdown. + if ((instance_count_ == 0) && webkit_glue::IsPluginRunningInRendererProcess()) + Unload(); +} + +bool PluginLib::Load() { + if (library_) + return true; + + bool rv = false; + base::NativeLibrary library = 0; + + if (!internal_) { +#if defined(OS_WIN) + // This is to work around a bug in the Real player recorder plugin which + // intercepts LoadLibrary calls from chrome.dll and wraps NPAPI functions + // provided by the plugin. It crashes if the media player plugin is being + // loaded. Workaround is to load the dll dynamically by getting the + // LoadLibrary API address from kernel32.dll which bypasses the recorder + // plugin. + if (web_plugin_info_.name.find(L"Windows Media Player") != + std::wstring::npos) { + library = base::LoadNativeLibraryDynamically(web_plugin_info_.path); + } else { + library = base::LoadNativeLibrary(web_plugin_info_.path); + } +#else // OS_WIN + library = base::LoadNativeLibrary(web_plugin_info_.path); +#endif // OS_WIN + if (library == 0) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Couldn't load plugin " << web_plugin_info_.path.value(); + return rv; + } + +#if defined(OS_MACOSX) + // According to the WebKit source, QuickTime at least requires us to call + // UseResFile on the plugin resources before loading. + if (library->bundle_resource_ref != -1) + UseResFile(library->bundle_resource_ref); +#endif + + rv = true; // assume success now + + entry_points_.np_initialize = + (NP_InitializeFunc)base::GetFunctionPointerFromNativeLibrary(library, + "NP_Initialize"); + if (entry_points_.np_initialize == 0) + rv = false; + +#if defined(OS_WIN) || defined(OS_MACOSX) + entry_points_.np_getentrypoints = + (NP_GetEntryPointsFunc)base::GetFunctionPointerFromNativeLibrary( + library, "NP_GetEntryPoints"); + if (entry_points_.np_getentrypoints == 0) + rv = false; +#endif + + entry_points_.np_shutdown = + (NP_ShutdownFunc)base::GetFunctionPointerFromNativeLibrary(library, + "NP_Shutdown"); + if (entry_points_.np_shutdown == 0) + rv = false; + } else { + rv = true; + } + + if (rv) { + plugin_funcs_.size = sizeof(plugin_funcs_); + plugin_funcs_.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; +#if !defined(OS_POSIX) + if (entry_points_.np_getentrypoints(&plugin_funcs_) != NPERR_NO_ERROR) + rv = false; +#else + // On Linux and Mac, we get the plugin entry points during NP_Initialize. +#endif + } + + if (!internal_) { + if (rv) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Plugin " << web_plugin_info_.path.value() + << " loaded successfully."; + library_ = library; + } else { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Plugin " << web_plugin_info_.path.value() + << " failed to load, unloading."; + base::UnloadNativeLibrary(library); + } + } + + return rv; +} + +// This class implements delayed NP_Shutdown and FreeLibrary on the plugin dll. +class FreePluginLibraryTask : public Task { + public: + FreePluginLibraryTask(const FilePath& path, + base::NativeLibrary library, + NP_ShutdownFunc shutdown_func) + : path_(path), + library_(library), + NP_Shutdown_(shutdown_func) { + } + + ~FreePluginLibraryTask() {} + + void Run() { + if (NP_Shutdown_) { + // Don't call NP_Shutdown if the library has been reloaded since this task + // was posted. + bool reloaded = false; + if (g_loaded_libs) { + for (size_t i = 0; i < g_loaded_libs->size(); ++i) { + if ((*g_loaded_libs)[i]->plugin_info().path == path_) + reloaded = true; + } + } + if (!reloaded) + NP_Shutdown_(); + } + + if (library_) { + // Always call base::UnloadNativeLibrary so that the system reference + // count is decremented. + base::UnloadNativeLibrary(library_); + library_ = NULL; + } + } + + private: + FilePath path_; + base::NativeLibrary library_; + NP_ShutdownFunc NP_Shutdown_; + DISALLOW_COPY_AND_ASSIGN(FreePluginLibraryTask); +}; + +void PluginLib::Unload() { + if (!internal_ && library_) { + // In case of single process mode, a plugin can delete itself + // by executing a script. So delay the unloading of the library + // so that the plugin will have a chance to unwind. + bool defer_unload = webkit_glue::IsPluginRunningInRendererProcess(); + +/* TODO(dglazkov): Revisit when re-enabling the JSC build. +#if USE(JSC) + // The plugin NPAPI instances may still be around. Delay the + // NP_Shutdown and FreeLibrary calls at least till the next + // peek message. + defer_unload = true; +#endif +*/ + + if (defer_unload) { + FreePluginLibraryTask* free_library_task = + new FreePluginLibraryTask(web_plugin_info_.path, + skip_unload_ ? NULL : library_, + entry_points_.np_shutdown); + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Scheduling delayed unload for plugin " + << web_plugin_info_.path.value(); + MessageLoop::current()->PostTask(FROM_HERE, free_library_task); + } else { + Shutdown(); + if (!skip_unload_) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Unloading plugin " << web_plugin_info_.path.value(); + base::UnloadNativeLibrary(library_); + } + } + + library_ = NULL; + } + + for (size_t i = 0; i < g_loaded_libs->size(); ++i) { + if ((*g_loaded_libs)[i].get() == this) { + g_loaded_libs->erase(g_loaded_libs->begin() + i); + break; + } + } + if (g_loaded_libs->empty()) { + delete g_loaded_libs; + g_loaded_libs = NULL; + } +} + +void PluginLib::Shutdown() { + if (initialized_ && !internal_) { + NP_Shutdown(); + initialized_ = false; + } +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_lib.h b/webkit/glue/plugins/plugin_lib.h new file mode 100644 index 0000000..ca46e41 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib.h @@ -0,0 +1,120 @@ +// 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 WEBKIT_GLUE_PLUGINS_PLUGIN_LIB_H_ +#define WEBKIT_GLUE_PLUGINS_PLUGIN_LIB_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/native_library.h" +#include "base/ref_counted.h" +#include "build/build_config.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/webplugin.h" + +class FilePath; +struct WebPluginInfo; + +namespace NPAPI { + +class PluginInstance; + +// A PluginLib is a single NPAPI Plugin Library, and is the lifecycle +// manager for new PluginInstances. +class PluginLib : public base::RefCounted { + public: + static PluginLib* CreatePluginLib(const FilePath& filename); + + // Creates a WebPluginInfo structure given a plugin's path. On success + // returns true, with the information being put into "info". + // Returns false if the library couldn't be found, or if it's not a plugin. + static bool ReadWebPluginInfo(const FilePath& filename, WebPluginInfo* info); + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + // Parse the result of an NP_GetMIMEDescription() call. + // This API is only used on Unixes, and is exposed here for testing. + static void ParseMIMEDescription(const std::string& description, + std::vector* mime_types); +#endif + + // Unloads all the loaded plugin libraries and cleans up the plugin map. + static void UnloadAllPlugins(); + + // Shuts down all loaded plugin instances. + static void ShutdownAllPlugins(); + + // Get the Plugin's function pointer table. + NPPluginFuncs* functions(); + + // Creates a new instance of this plugin. + PluginInstance* CreateInstance(const std::string& mime_type); + + // Called by the instance when the instance is tearing down. + void CloseInstance(); + + // Gets information about this plugin and the mime types that it + // supports. + const WebPluginInfo& plugin_info() { return web_plugin_info_; } + + bool internal() { return internal_; } + + // + // NPAPI functions + // + + // NPAPI method to initialize a Plugin. + // Initialize can be safely called multiple times + NPError NP_Initialize(); + + // NPAPI method to shutdown a Plugin. + void NP_Shutdown(void); + + int instance_count() const { return instance_count_; } + + // Prevents the library code from being unload when Unload() is called (since + // some plugins crash if unloaded). + void PreventLibraryUnload(); + + // protected for testability. + protected: + friend class base::RefCounted; + + // Creates a new PluginLib. + // |entry_points| is non-NULL for internal plugins. + PluginLib(const WebPluginInfo& info, + const PluginEntryPoints* entry_points); + + virtual ~PluginLib(); + + // Attempts to load the plugin from the library. + // Returns true if it is a legitimate plugin, false otherwise + bool Load(); + + // Unloads the plugin library. + void Unload(); + + // Shutdown the plugin library. + void Shutdown(); + + private: + bool internal_; // True for plugins that are built-in into chrome binaries. + WebPluginInfo web_plugin_info_; // Supported mime types, description + base::NativeLibrary library_; // The opened library reference. + NPPluginFuncs plugin_funcs_; // The struct of plugin side functions. + bool initialized_; // Is the plugin initialized? + NPSavedData *saved_data_; // Persisted plugin info for NPAPI. + int instance_count_; // Count of plugins in use. + bool skip_unload_; // True if library_ should not be unloaded. + + // Function pointers to entry points into the plugin. + PluginEntryPoints entry_points_; + + DISALLOW_COPY_AND_ASSIGN(PluginLib); +}; + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGINS_PLUGIN_LIB_H_ diff --git a/webkit/glue/plugins/plugin_lib_mac.mm b/webkit/glue/plugins/plugin_lib_mac.mm new file mode 100644 index 0000000..89444c8 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib_mac.mm @@ -0,0 +1,348 @@ +// 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. + +#import + +#include "webkit/glue/plugins/plugin_lib.h" + +#include "base/mac/scoped_cftyperef.h" +#include "base/native_library.h" +#include "base/scoped_ptr.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "webkit/glue/plugins/plugin_list.h" + +static const short kSTRTypeDefinitionResourceID = 128; +static const short kSTRTypeDescriptionResourceID = 127; +static const short kSTRPluginDescriptionResourceID = 126; + +using base::mac::ScopedCFTypeRef; + +namespace NPAPI { + +namespace { + +NSDictionary* GetMIMETypes(CFBundleRef bundle) { + NSString* mime_filename = + (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("WebPluginMIMETypesFilename")); + + if (mime_filename) { + + // get the file + + NSString* mime_path = + [NSString stringWithFormat:@"%@/Library/Preferences/%@", + NSHomeDirectory(), mime_filename]; + NSDictionary* mime_file_dict = + [NSDictionary dictionaryWithContentsOfFile:mime_path]; + + // is it valid? + + bool valid_file = false; + if (mime_file_dict) { + NSString* l10n_name = + [mime_file_dict objectForKey:@"WebPluginLocalizationName"]; + NSString* preferred_l10n = [[NSLocale currentLocale] localeIdentifier]; + if ([l10n_name isEqualToString:preferred_l10n]) + valid_file = true; + } + + if (valid_file) + return [mime_file_dict objectForKey:@"WebPluginMIMETypes"]; + + // dammit, I didn't want to have to do this + + typedef void (*CreateMIMETypesPrefsPtr)(void); + CreateMIMETypesPrefsPtr create_prefs_file = + (CreateMIMETypesPrefsPtr)CFBundleGetFunctionPointerForName( + bundle, CFSTR("BP_CreatePluginMIMETypesPreferences")); + if (!create_prefs_file) + return nil; + create_prefs_file(); + + // one more time + + mime_file_dict = [NSDictionary dictionaryWithContentsOfFile:mime_path]; + if (mime_file_dict) + return [mime_file_dict objectForKey:@"WebPluginMIMETypes"]; + else + return nil; + + } else { + return (NSDictionary*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("WebPluginMIMETypes")); + } +} + +bool ReadPlistPluginInfo(const FilePath& filename, CFBundleRef bundle, + WebPluginInfo* info) { + NSDictionary* mime_types = GetMIMETypes(bundle); + if (!mime_types) + return false; // no type info here; try elsewhere + + for (NSString* mime_type in [mime_types allKeys]) { + NSDictionary* mime_dict = [mime_types objectForKey:mime_type]; + NSString* mime_desc = [mime_dict objectForKey:@"WebPluginTypeDescription"]; + NSArray* mime_exts = [mime_dict objectForKey:@"WebPluginExtensions"]; + + WebPluginMimeType mime; + mime.mime_type = base::SysNSStringToUTF8([mime_type lowercaseString]); + // Remove PDF from the list of types handled by QuickTime, since it provides + // a worse experience than just downloading the PDF. + if (mime.mime_type == "application/pdf" && + StartsWithASCII(filename.BaseName().value(), "QuickTime", false)) { + continue; + } + + if (mime_desc) + mime.description = base::SysNSStringToUTF16(mime_desc); + for (NSString* ext in mime_exts) + mime.file_extensions.push_back( + base::SysNSStringToUTF8([ext lowercaseString])); + + info->mime_types.push_back(mime); + } + + NSString* plugin_name = + (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("WebPluginName")); + NSString* plugin_vers = + (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("CFBundleShortVersionString")); + NSString* plugin_desc = + (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("WebPluginDescription")); + + if (plugin_name) + info->name = base::SysNSStringToUTF16(plugin_name); + else + info->name = UTF8ToUTF16(filename.BaseName().value()); + info->path = filename; + if (plugin_vers) + info->version = base::SysNSStringToUTF16(plugin_vers); + if (plugin_desc) + info->desc = base::SysNSStringToUTF16(plugin_desc); + else + info->desc = UTF8ToUTF16(filename.BaseName().value()); + info->enabled = true; + + return true; +} + +class ScopedBundleResourceFile { + public: + ScopedBundleResourceFile(CFBundleRef bundle) : bundle_(bundle) { + old_ref_num_ = CurResFile(); + bundle_ref_num_ = CFBundleOpenBundleResourceMap(bundle); + UseResFile(bundle_ref_num_); + } + ~ScopedBundleResourceFile() { + UseResFile(old_ref_num_); + CFBundleCloseBundleResourceMap(bundle_, bundle_ref_num_); + } + + private: + CFBundleRef bundle_; + CFBundleRefNum bundle_ref_num_; + ResFileRefNum old_ref_num_; +}; + +bool GetSTRResource(CFBundleRef bundle, short res_id, + std::vector* contents) { + Handle res_handle = Get1Resource('STR#', res_id); + if (!res_handle || !*res_handle) + return false; + + char* pointer = *res_handle; + short num_strings = *(short*)pointer; + pointer += sizeof(short); + for (short i = 0; i < num_strings; ++i) { + // Despite being 8-bits wide, these are legacy encoded. Make a round trip. + ScopedCFTypeRef str(CFStringCreateWithPascalStringNoCopy( + kCFAllocatorDefault, + (unsigned char*)pointer, + GetApplicationTextEncoding(), // is this right? + kCFAllocatorNull)); // perhaps CFStringGetSystemEncoding? + if (!str.get()) + return false; + contents->push_back(base::SysCFStringRefToUTF8(str.get())); + pointer += 1+*reinterpret_cast(pointer); + } + + return true; +} + +bool ReadSTRPluginInfo(const FilePath& filename, CFBundleRef bundle, + WebPluginInfo* info) { + ScopedBundleResourceFile res_file(bundle); + + std::vector type_strings; + if (!GetSTRResource(bundle, kSTRTypeDefinitionResourceID, &type_strings)) + return false; + + std::vector type_descs; + bool have_type_descs = GetSTRResource(bundle, + kSTRTypeDescriptionResourceID, + &type_descs); + + std::vector plugin_descs; + bool have_plugin_descs = GetSTRResource(bundle, + kSTRPluginDescriptionResourceID, + &plugin_descs); + + size_t num_types = type_strings.size()/2; + + for (size_t i = 0; i < num_types; ++i) { + WebPluginMimeType mime; + mime.mime_type = StringToLowerASCII(type_strings[2*i]); + if (have_type_descs && i < type_descs.size()) + mime.description = UTF8ToUTF16(type_descs[i]); + base::SplitString( + StringToLowerASCII(type_strings[2*i+1]), ',', &mime.file_extensions); + + info->mime_types.push_back(mime); + } + + NSString* plugin_vers = + (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle, + CFSTR("CFBundleShortVersionString")); + + if (have_plugin_descs && plugin_descs.size() > 1) + info->name = UTF8ToUTF16(plugin_descs[1]); + else + info->name = UTF8ToUTF16(filename.BaseName().value()); + info->path = filename; + if (plugin_vers) + info->version = base::SysNSStringToUTF16(plugin_vers); + if (have_plugin_descs && plugin_descs.size() > 0) + info->desc = UTF8ToUTF16(plugin_descs[0]); + else + info->desc = UTF8ToUTF16(filename.BaseName().value()); + info->enabled = true; + + return true; +} + +} // anonymous namespace + +bool PluginLib::ReadWebPluginInfo(const FilePath &filename, + WebPluginInfo* info) { + // There are two ways to get information about plugin capabilities. One is an + // Info.plist set of keys, documented at + // http://developer.apple.com/documentation/InternetWeb/Conceptual/WebKit_PluginProgTopic/Concepts/AboutPlugins.html . + // The other is a set of STR# resources, documented at + // https://developer.mozilla.org/En/Gecko_Plugin_API_Reference/Plug-in_Development_Overview . + // + // Historically, the data was maintained in the STR# resources. Apple, with + // the introduction of WebKit, noted the weaknesses of resources and moved the + // information into the Info.plist. Mozilla had always supported a + // NP_GetMIMEDescription() entry point for Unix plugins and also supports it + // on the Mac to supplement the STR# format. WebKit does not support + // NP_GetMIMEDescription() and neither do we. (That entry point is documented + // at https://developer.mozilla.org/en/NP_GetMIMEDescription .) We prefer the + // Info.plist format because it's more extensible and has a defined encoding, + // but will fall back to the STR# format of the data if it is not present in + // the Info.plist. + // + // The parsing of the data lives in the two functions ReadSTRPluginInfo() and + // ReadPlistPluginInfo(), but a summary of the formats follows. + // + // Each data type handled by a plugin has several properties: + // - <> + // - <>..<> + // - <> + // + // Each plugin may have any number of types defined. In addition, the plugin + // itself has properties: + // - <> + // - <> + // + // For the Info.plist version, the data is formatted as follows (in text plist + // format): + // { + // ... the usual plist keys ... + // WebPluginDescription = <>; + // WebPluginMIMETypes = { + // <> = { + // WebPluginExtensions = ( + // <>, + // ... + // <>, + // ); + // WebPluginTypeDescription = <>; + // }; + // <> = { ... }; + // ... + // <> = { ... }; + // }; + // WebPluginName = <>; + // } + // + // Alternatively (and this is undocumented), rather than a WebPluginMIMETypes + // key, there may be a WebPluginMIMETypesFilename key. If it is present, then + // it is the name of a file in the user's preferences folder in which to find + // the WebPluginMIMETypes key. If the key is present but the file doesn't + // exist, we must load the plugin and call a specific function to have the + // plugin create the file. + // + // If we do not find those keys in the Info.plist, we fall back to the STR# + // resources. In them, the data is formatted as follows: + // STR# 128 + // (1) <> + // (2) <>,...,<> + // (3) <> + // (4) <>,...,<> + // (...) + // (2n+1) <> + // (2n+2) <>,...,<> + // STR# 127 + // (1) <> + // (2) <> + // (...) + // (n+1) <> + // STR# 126 + // (1) <> + // (2) <> + // + // Strictly speaking, only STR# 128 is required. + + ScopedCFTypeRef bundle_url(CFURLCreateFromFileSystemRepresentation( + kCFAllocatorDefault, (const UInt8*)filename.value().c_str(), + filename.value().length(), true)); + if (!bundle_url) + return false; + ScopedCFTypeRef bundle(CFBundleCreate(kCFAllocatorDefault, + bundle_url.get())); + if (!bundle) + return false; + + // preflight + + OSType type = 0; + CFBundleGetPackageInfo(bundle.get(), &type, NULL); + if (type != FOUR_CHAR_CODE('BRPL')) + return false; + + CFErrorRef error; + Boolean would_load = CFBundlePreflightExecutable(bundle.get(), &error); + if (!would_load) + return false; + + // get the info + + if (ReadPlistPluginInfo(filename, bundle.get(), info)) + return true; + + if (ReadSTRPluginInfo(filename, bundle.get(), info)) + return true; + + // ... or not + + return false; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_lib_posix.cc b/webkit/glue/plugins/plugin_lib_posix.cc new file mode 100644 index 0000000..ac937e1 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib_posix.cc @@ -0,0 +1,256 @@ +// 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 "webkit/glue/plugins/plugin_lib.h" + +#include +#if defined(OS_OPENBSD) +#include +#else +#include +#include +#endif +#include +#include +#include + +#include "base/eintr_wrapper.h" +#include "base/file_util.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "webkit/glue/plugins/plugin_list.h" + +// These headers must be included in this order to make the declaration gods +// happy. +#include "base/third_party/nspr/prcpucfg_linux.h" + +namespace { + +using NPAPI::PluginList; + +// Copied from nsplugindefs.h instead of including the file since it has a bunch +// of dependencies. +enum nsPluginVariable { + nsPluginVariable_NameString = 1, + nsPluginVariable_DescriptionString = 2 +}; + +// Read the ELF header and return true if it is usable on +// the current architecture (e.g. 32-bit ELF on 32-bit build). +// Returns false on other errors as well. +bool ELFMatchesCurrentArchitecture(const FilePath& filename) { + // First make sure we can open the file and it is in fact, a regular file. + struct stat stat_buf; + // Open with O_NONBLOCK so we don't block on pipes. + int fd = open(filename.value().c_str(), O_RDONLY|O_NONBLOCK); + if (fd < 0) + return false; + bool ret = (fstat(fd, &stat_buf) >= 0 && S_ISREG(stat_buf.st_mode)); + if (HANDLE_EINTR(close(fd)) < 0) + return false; + if (!ret) + return false; + + const size_t kELFBufferSize = 5; + char buffer[kELFBufferSize]; + if (!file_util::ReadFile(filename, buffer, kELFBufferSize)) + return false; + + if (buffer[0] != ELFMAG0 || + buffer[1] != ELFMAG1 || + buffer[2] != ELFMAG2 || + buffer[3] != ELFMAG3) { + // Not an ELF file, perhaps? + return false; + } + + int elf_class = buffer[EI_CLASS]; +#if defined(ARCH_CPU_32_BITS) + if (elf_class == ELFCLASS32) + return true; +#elif defined(ARCH_CPU_64_BITS) + if (elf_class == ELFCLASS64) + return true; +#endif + + return false; +} + +// This structure matches enough of nspluginwrapper's NPW_PluginInfo +// for us to extract the real plugin path. +struct __attribute__((packed)) NSPluginWrapperInfo { + char ident[32]; // NSPluginWrapper magic identifier (includes version). + char path[PATH_MAX]; // Path to wrapped plugin. +}; + +// Test a plugin for whether it's been wrapped by NSPluginWrapper, and +// if so attempt to unwrap it. Pass in an opened plugin handle; on +// success, |dl| and |unwrapped_path| will be filled in with the newly +// opened plugin. On failure, params are left unmodified. +void UnwrapNSPluginWrapper(void **dl, FilePath* unwrapped_path) { + NSPluginWrapperInfo* info = + reinterpret_cast(dlsym(*dl, "NPW_Plugin")); + if (!info) + return; // Not a NSPW plugin. + + // Here we could check the NSPW ident field for the versioning + // information, but the path field is available in all versions + // anyway. + + // Grab the path to the wrapped plugin. Just in case the structure + // format changes, protect against the path not being null-terminated. + char* path_end = static_cast(memchr(info->path, '\0', + sizeof(info->path))); + if (!path_end) + path_end = info->path + sizeof(info->path); + FilePath path = FilePath(std::string(info->path, path_end - info->path)); + + if (!ELFMatchesCurrentArchitecture(path)) { + LOG(WARNING) << path.value() << " is nspluginwrapper wrapping a " + << "plugin for a different architecture; it will " + << "work better if you instead use a native plugin."; + return; + } + + void* newdl = base::LoadNativeLibrary(path); + if (!newdl) { + // We couldn't load the unwrapped plugin for some reason, despite + // being able to load the wrapped one. Just use the wrapped one. + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Could not use unwrapped nspluginwrapper plugin " + << unwrapped_path->value() << ", using the wrapped one."; + return; + } + + // Unload the wrapped plugin, and use the wrapped plugin instead. + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Using unwrapped version " << unwrapped_path->value() + << " of nspluginwrapper-wrapped plugin."; + base::UnloadNativeLibrary(*dl); + *dl = newdl; + *unwrapped_path = path; +} + +} // anonymous namespace + +namespace NPAPI { + +bool PluginLib::ReadWebPluginInfo(const FilePath& filename, + WebPluginInfo* info) { + // The file to reference is: + // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUnix.cpp + + // Skip files that aren't appropriate for our architecture. + if (!ELFMatchesCurrentArchitecture(filename)) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Skipping plugin " << filename.value() + << " because it doesn't match the current architecture."; + return false; + } + + void* dl = base::LoadNativeLibrary(filename); + if (!dl) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "While reading plugin info, unable to load library " + << filename.value() << ", skipping."; + return false; + } + + info->path = filename; + info->enabled = true; + + // Attempt to swap in the wrapped plugin if this is nspluginwrapper. + UnwrapNSPluginWrapper(&dl, &info->path); + + // See comments in plugin_lib_mac regarding this symbol. + typedef const char* (*NP_GetMimeDescriptionType)(); + NP_GetMimeDescriptionType NP_GetMIMEDescription = + reinterpret_cast( + dlsym(dl, "NP_GetMIMEDescription")); + const char* mime_description = NULL; + if (NP_GetMIMEDescription) + mime_description = NP_GetMIMEDescription(); + + if (mime_description) + ParseMIMEDescription(mime_description, &info->mime_types); + + // The plugin name and description live behind NP_GetValue calls. + typedef NPError (*NP_GetValueType)(void* unused, + nsPluginVariable variable, + void* value_out); + NP_GetValueType NP_GetValue = + reinterpret_cast(dlsym(dl, "NP_GetValue")); + if (NP_GetValue) { + const char* name = NULL; + NP_GetValue(NULL, nsPluginVariable_NameString, &name); + if (name) + info->name = UTF8ToUTF16(name); + + const char* description = NULL; + NP_GetValue(NULL, nsPluginVariable_DescriptionString, &description); + if (description) + info->desc = UTF8ToUTF16(description); + + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Got info for plugin " << filename.value() + << " Name = \"" << UTF16ToUTF8(info->name) + << "\", Description = \"" << UTF16ToUTF8(info->desc) << "\"."; + } else { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Plugin " << filename.value() + << " has no GetValue() and probably won't work."; + } + + // Intentionally not unloading the plugin here, it can lead to crashes. + + return true; +} + +// static +void PluginLib::ParseMIMEDescription( + const std::string& description, + std::vector* mime_types) { + // We parse the description here into WebPluginMimeType structures. + // Naively from the NPAPI docs you'd think you could use + // string-splitting, but the Firefox parser turns out to do something + // different: find the first colon, then the second, then a semi. + // + // See ParsePluginMimeDescription near + // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginsDirUtils.h#53 + + std::string::size_type ofs = 0; + for (;;) { + WebPluginMimeType mime_type; + + std::string::size_type end = description.find(':', ofs); + if (end == std::string::npos) + break; + mime_type.mime_type = description.substr(ofs, end - ofs); + ofs = end + 1; + + end = description.find(':', ofs); + if (end == std::string::npos) + break; + const std::string extensions = description.substr(ofs, end - ofs); + base::SplitString(extensions, ',', &mime_type.file_extensions); + ofs = end + 1; + + end = description.find(';', ofs); + // It's ok for end to run off the string here. If there's no + // trailing semicolon we consume the remainder of the string. + if (end != std::string::npos) { + mime_type.description = UTF8ToUTF16(description.substr(ofs, end - ofs)); + } else { + mime_type.description = UTF8ToUTF16(description.substr(ofs)); + } + mime_types->push_back(mime_type); + if (end == std::string::npos) + break; + ofs = end + 1; + } +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_lib_unittest.cc b/webkit/glue/plugins/plugin_lib_unittest.cc new file mode 100644 index 0000000..45c4bb6 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib_unittest.cc @@ -0,0 +1,152 @@ +// 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 "webkit/glue/plugins/plugin_lib.h" + +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Test the unloading of plugin libs. Bug http://crbug.com/46526 showed that +// if UnloadAllPlugins() simply iterates through the g_loaded_libs global +// variable, we can get a crash if no plugin libs were marked as always loaded. +class PluginLibTest : public NPAPI::PluginLib { + public: + PluginLibTest() : NPAPI::PluginLib(WebPluginInfo(), NULL) { + } + using NPAPI::PluginLib::Unload; +}; + +TEST(PluginLibLoading, UnloadAllPlugins) { + // For the creation of the g_loaded_libs global variable. + ASSERT_EQ(static_cast(NULL), + PluginLibTest::CreatePluginLib(FilePath())); + + // Try with a single plugin lib. + scoped_refptr plugin_lib1(new PluginLibTest()); + NPAPI::PluginLib::UnloadAllPlugins(); + + // Need to create it again, it should have been destroyed above. + ASSERT_EQ(static_cast(NULL), + PluginLibTest::CreatePluginLib(FilePath())); + + // Try with two plugin libs. + plugin_lib1 = new PluginLibTest(); + scoped_refptr plugin_lib2(new PluginLibTest()); + NPAPI::PluginLib::UnloadAllPlugins(); + + // Need to create it again, it should have been destroyed above. + ASSERT_EQ(static_cast(NULL), + PluginLibTest::CreatePluginLib(FilePath())); + + // Now try to manually Unload one and then UnloadAll. + plugin_lib1 = new PluginLibTest(); + plugin_lib2 = new PluginLibTest(); + plugin_lib1->Unload(); + NPAPI::PluginLib::UnloadAllPlugins(); + + // Need to create it again, it should have been destroyed above. + ASSERT_EQ(static_cast(NULL), + PluginLibTest::CreatePluginLib(FilePath())); + + // Now try to manually Unload the only one and then UnloadAll. + plugin_lib1 = new PluginLibTest(); + plugin_lib1->Unload(); + NPAPI::PluginLib::UnloadAllPlugins(); +} + +#if defined(OS_LINUX) + +// Test parsing a simple description: Real Audio. +TEST(MIMEDescriptionParse, Simple) { + std::vector types; + NPAPI::PluginLib::ParseMIMEDescription( + "audio/x-pn-realaudio-plugin:rpm:RealAudio document;", + &types); + ASSERT_EQ(1U, types.size()); + const WebPluginMimeType& type = types[0]; + EXPECT_EQ("audio/x-pn-realaudio-plugin", type.mime_type); + ASSERT_EQ(1U, type.file_extensions.size()); + EXPECT_EQ("rpm", type.file_extensions[0]); + EXPECT_EQ(ASCIIToUTF16("RealAudio document"), type.description); +} + +// Test parsing a multi-entry description: QuickTime as provided by Totem. +TEST(MIMEDescriptionParse, Multi) { + std::vector types; + NPAPI::PluginLib::ParseMIMEDescription( + "video/quicktime:mov:QuickTime video;video/mp4:mp4:MPEG-4 " + "video;image/x-macpaint:pntg:MacPaint Bitmap image;image/x" + "-quicktime:pict, pict1, pict2:QuickTime image;video/x-m4v" + ":m4v:MPEG-4 video;", + &types); + + ASSERT_EQ(5U, types.size()); + + // Check the x-quicktime one, since it looks tricky with spaces in the + // extension list. + const WebPluginMimeType& type = types[3]; + EXPECT_EQ("image/x-quicktime", type.mime_type); + ASSERT_EQ(3U, type.file_extensions.size()); + EXPECT_EQ("pict2", type.file_extensions[2]); + EXPECT_EQ(ASCIIToUTF16("QuickTime image"), type.description); +} + +// Test parsing a Japanese description, since we got this wrong in the past. +// This comes from loading Totem with LANG=ja_JP.UTF-8. +TEST(MIMEDescriptionParse, JapaneseUTF8) { + std::vector types; + NPAPI::PluginLib::ParseMIMEDescription( + "audio/x-ogg:ogg:Ogg \xe3\x82\xaa\xe3\x83\xbc\xe3\x83\x87" + "\xe3\x82\xa3\xe3\x83\xaa", + &types); + + ASSERT_EQ(1U, types.size()); + // Check we got the right number of Unicode characters out of the parse. + EXPECT_EQ(9U, types[0].description.size()); +} + +// Test that we handle corner cases gracefully. +TEST(MIMEDescriptionParse, CornerCases) { + std::vector types; + NPAPI::PluginLib::ParseMIMEDescription("mime/type:", &types); + EXPECT_TRUE(types.empty()); + + types.clear(); + NPAPI::PluginLib::ParseMIMEDescription("mime/type:ext1:", &types); + ASSERT_EQ(1U, types.size()); + EXPECT_EQ("mime/type", types[0].mime_type); + EXPECT_EQ(1U, types[0].file_extensions.size()); + EXPECT_EQ("ext1", types[0].file_extensions[0]); + EXPECT_EQ(string16(), types[0].description); +} + +// This Java plugin has embedded semicolons in the mime type. +TEST(MIMEDescriptionParse, ComplicatedJava) { + std::vector types; + NPAPI::PluginLib::ParseMIMEDescription( + "application/x-java-vm:class,jar:IcedTea;application/x-java" + "-applet:class,jar:IcedTea;application/x-java-applet;versio" + "n=1.1:class,jar:IcedTea;application/x-java-applet;version=" + "1.1.1:class,jar:IcedTea;application/x-java-applet;version=" + "1.1.2:class,jar:IcedTea;application/x-java-applet;version=" + "1.1.3:class,jar:IcedTea;application/x-java-applet;version=" + "1.2:class,jar:IcedTea;application/x-java-applet;version=1." + "2.1:class,jar:IcedTea;application/x-java-applet;version=1." + "2.2:class,jar:IcedTea;application/x-java-applet;version=1." + "3:class,jar:IcedTea;application/x-java-applet;version=1.3." + "1:class,jar:IcedTea;application/x-java-applet;version=1.4:" + "class,jar:IcedTea", + &types); + + ASSERT_EQ(12U, types.size()); + for (size_t i = 0; i < types.size(); ++i) + EXPECT_EQ(ASCIIToUTF16("IcedTea"), types[i].description); + + // Verify that the mime types with semis are coming through ok. + EXPECT_TRUE(types[4].mime_type.find(';') != std::string::npos); +} + +#endif // defined(OS_LINUX) diff --git a/webkit/glue/plugins/plugin_lib_win.cc b/webkit/glue/plugins/plugin_lib_win.cc new file mode 100644 index 0000000..382c2c8 --- /dev/null +++ b/webkit/glue/plugins/plugin_lib_win.cc @@ -0,0 +1,46 @@ +// 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 "webkit/glue/plugins/plugin_lib.h" + +#include "base/file_version_info.h" +#include "base/file_version_info_win.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_list.h" + +namespace NPAPI { + +bool PluginLib::ReadWebPluginInfo(const FilePath &filename, + WebPluginInfo* info) { + // On windows, the way we get the mime types for the library is + // to check the version information in the DLL itself. This + // will be a string of the format: |||... + // For example: + // video/quicktime|audio/aiff|image/jpeg + scoped_ptr version_info( + FileVersionInfo::CreateFileVersionInfo(filename.value())); + if (!version_info.get()) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Could not get version info for plugin " + << filename.value(); + return false; + } + + FileVersionInfoWin* version_info_win = + static_cast(version_info.get()); + PluginVersionInfo pvi; + pvi.mime_types = version_info_win->GetStringValue(L"MIMEType"); + pvi.file_extensions = version_info_win->GetStringValue(L"FileExtents"); + pvi.type_descriptions = version_info_win->GetStringValue(L"FileOpenName"); + pvi.product_name = version_info->product_name(); + pvi.file_description = version_info->file_description(); + pvi.file_version = version_info->file_version(); + pvi.path = filename; + + return PluginList::CreateWebPluginInfo(pvi, info); +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc new file mode 100644 index 0000000..a2b4cf5 --- /dev/null +++ b/webkit/glue/plugins/plugin_list.cc @@ -0,0 +1,781 @@ +// 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 "webkit/glue/plugins/plugin_list.h" + +#include + +#include "base/command_line.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" +#include "googleurl/src/gurl.h" +#include "net/base/mime_util.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/plugins/plugin_switches.h" + +#if defined(OS_POSIX) +#include "base/stl_util-inl.h" +#include "base/third_party/valgrind/valgrind.h" +#endif // defined(OS_POSIX) + +namespace NPAPI { + +#if defined(OS_MACOSX) +// Plugin Groups for Mac. +// Plugins are listed here as soon as vulnerabilities and solutions +// (new versions) are published. +// TODO(panayiotis): Get the Real Player version on Mac, somehow. +static const VersionRangeDefinition kQuicktimeVersionRange[] = { + { "", "", "7.6.6" } +}; +static const VersionRangeDefinition kJavaVersionRange[] = { + { "", "", "" } +}; +static const VersionRangeDefinition kFlashVersionRange[] = { + { "", "", "10.1.102" } +}; +static const VersionRangeDefinition kSilverlightVersionRange[] = { + { "0", "4", "3.0.50106.0" }, + { "4", "5", "" } +}; +static const VersionRangeDefinition kFlip4MacVersionRange[] = { + { "", "", "2.2.1" } +}; +static const VersionRangeDefinition kShockwaveVersionRange[] = { + { "", "", "11.5.9.615" } +}; +static const PluginGroupDefinition kGroupDefinitions[] = { + { "apple-quicktime", "Quicktime", "QuickTime Plug-in", kQuicktimeVersionRange, + arraysize(kQuicktimeVersionRange), + "http://www.apple.com/quicktime/download/" }, + { "java-runtime-environment", "Java", "Java", kJavaVersionRange, + arraysize(kJavaVersionRange), "http://support.apple.com/kb/HT1338" }, + { "adobe-flash-player", "Flash", "Shockwave Flash", kFlashVersionRange, + arraysize(kFlashVersionRange), "http://get.adobe.com/flashplayer/" }, + { "silverlight", "Silverlight", "Silverlight", kSilverlightVersionRange, + arraysize(kSilverlightVersionRange), + "http://www.microsoft.com/getsilverlight/" }, + { "flip4mac", "Flip4Mac", "Flip4Mac", kFlip4MacVersionRange, + arraysize(kFlip4MacVersionRange), + "http://www.telestream.net/flip4mac-wmv/overview.htm" }, + { "shockwave", "Shockwave", "Shockwave for Director", kShockwaveVersionRange, + arraysize(kShockwaveVersionRange), + "http://www.adobe.com/shockwave/download/" } +}; + +#elif defined(OS_WIN) +// TODO(panayiotis): We should group "RealJukebox NS Plugin" with the rest of +// the RealPlayer files. +static const VersionRangeDefinition kQuicktimeVersionRange[] = { + { "", "", "7.6.9" } +}; +static const VersionRangeDefinition kJavaVersionRange[] = { + { "0", "7", "6.0.220" } // "220" is not a typo. +}; +static const VersionRangeDefinition kAdobeReaderVersionRange[] = { + { "10", "11", "" }, + { "9", "10", "9.4.1" }, + { "0", "9", "8.2.5" } +}; +static const VersionRangeDefinition kFlashVersionRange[] = { + { "", "", "10.1.102" } +}; +static const VersionRangeDefinition kSilverlightVersionRange[] = { + { "0", "4", "3.0.50106.0" }, + { "4", "5", "" } +}; +static const VersionRangeDefinition kShockwaveVersionRange[] = { + { "", "", "11.5.9.615" } +}; +static const VersionRangeDefinition kDivXVersionRange[] = { + { "", "", "1.4.3.4" } +}; +static const VersionRangeDefinition kRealPlayerVersionRange[] = { + { "", "", "12.0.1.609" } +}; +static const PluginGroupDefinition kGroupDefinitions[] = { + { "apple-quicktime", "Quicktime", "QuickTime Plug-in", kQuicktimeVersionRange, + arraysize(kQuicktimeVersionRange), + "http://www.apple.com/quicktime/download/" }, + { "java-runtime-environment", "Java 6", "Java", kJavaVersionRange, + arraysize(kJavaVersionRange), "http://www.java.com/" }, + { "adobe-reader", PluginGroup::kAdobeReaderGroupName, "Adobe Acrobat", + kAdobeReaderVersionRange, arraysize(kAdobeReaderVersionRange), + "http://get.adobe.com/reader/" }, + { "adobe-flash-player", "Flash", "Shockwave Flash", kFlashVersionRange, + arraysize(kFlashVersionRange), "http://get.adobe.com/flashplayer/" }, + { "silverlight", "Silverlight", "Silverlight", kSilverlightVersionRange, + arraysize(kSilverlightVersionRange), + "http://www.microsoft.com/getsilverlight/" }, + { "shockwave", "Shockwave", "Shockwave for Director", kShockwaveVersionRange, + arraysize(kShockwaveVersionRange), + "http://www.adobe.com/shockwave/download/" }, + { "divx-player", "DivX Player", "DivX Web Player", kDivXVersionRange, + arraysize(kDivXVersionRange), + "http://download.divx.com/divx/autoupdate/player/" + "DivXWebPlayerInstaller.exe" }, + { "realplayer", "RealPlayer", "RealPlayer", kRealPlayerVersionRange, + arraysize(kRealPlayerVersionRange), + "http://www.real.com/realplayer" }, + // These are here for grouping, no vulnerabilities known. + { "windows-media-player", "Windows Media Player", "Windows Media Player", + NULL, 0, "" }, + { "microsoft-office", "Microsoft Office", "Microsoft Office", + NULL, 0, "" }, +}; + +#else +static const PluginGroupDefinition kGroupDefinitions[] = {}; +#endif + +// static +const PluginGroupDefinition* PluginList::GetPluginGroupDefinitions() { + return kGroupDefinitions; +} + +// static +size_t PluginList::GetPluginGroupDefinitionsSize() { + // TODO(viettrungluu): |arraysize()| doesn't work with zero-size arrays. + return ARRAYSIZE_UNSAFE(kGroupDefinitions); +} + +base::LazyInstance g_singleton(base::LINKER_INITIALIZED); + +// static +PluginList* PluginList::Singleton() { + return g_singleton.Pointer(); +} + +// static +bool PluginList::DebugPluginLoading() { + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDebugPluginLoading); +} + +bool PluginList::PluginsLoaded() { + AutoLock lock(lock_); + return plugins_loaded_; +} + +void PluginList::RefreshPlugins() { + AutoLock lock(lock_); + plugins_need_refresh_ = true; +} + +void PluginList::AddExtraPluginPath(const FilePath& plugin_path) { + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) + AutoLock lock(lock_); + extra_plugin_paths_.push_back(plugin_path); +#endif +} + +void PluginList::RemoveExtraPluginPath(const FilePath& plugin_path) { + AutoLock lock(lock_); + std::vector::iterator it = + std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(), + plugin_path); + if (it != extra_plugin_paths_.end()) + extra_plugin_paths_.erase(it); +} + +void PluginList::AddExtraPluginDir(const FilePath& plugin_dir) { + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) + AutoLock lock(lock_); + extra_plugin_dirs_.push_back(plugin_dir); +#endif +} + +void PluginList::RegisterInternalPlugin(const PluginVersionInfo& info) { + AutoLock lock(lock_); + internal_plugins_.push_back(info); +} + +void PluginList::UnregisterInternalPlugin(const FilePath& path) { + AutoLock lock(lock_); + for (size_t i = 0; i < internal_plugins_.size(); i++) { + if (internal_plugins_[i].path == path) { + internal_plugins_.erase(internal_plugins_.begin() + i); + return; + } + } + NOTREACHED(); +} + +bool PluginList::ReadPluginInfo(const FilePath& filename, + WebPluginInfo* info, + const PluginEntryPoints** entry_points) { + { + AutoLock lock(lock_); + for (size_t i = 0; i < internal_plugins_.size(); ++i) { + if (filename == internal_plugins_[i].path) { + *entry_points = &internal_plugins_[i].entry_points; + return CreateWebPluginInfo(internal_plugins_[i], info); + } + } + } + + // Not an internal plugin. + *entry_points = NULL; + + return PluginLib::ReadWebPluginInfo(filename, info); +} + +bool PluginList::CreateWebPluginInfo(const PluginVersionInfo& pvi, + WebPluginInfo* info) { + std::vector mime_types, file_extensions; + std::vector descriptions; + base::SplitString(WideToUTF8(pvi.mime_types), '|', &mime_types); + base::SplitString(WideToUTF8(pvi.file_extensions), '|', &file_extensions); + base::SplitString(WideToUTF16(pvi.type_descriptions), '|', &descriptions); + + info->mime_types.clear(); + + if (mime_types.empty()) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Plugin " << pvi.product_name << " has no MIME types, skipping"; + return false; + } + + info->name = WideToUTF16(pvi.product_name); + info->desc = WideToUTF16(pvi.file_description); + info->version = WideToUTF16(pvi.file_version); + info->path = pvi.path; + info->enabled = true; + + for (size_t i = 0; i < mime_types.size(); ++i) { + WebPluginMimeType mime_type; + mime_type.mime_type = StringToLowerASCII(mime_types[i]); + if (file_extensions.size() > i) + base::SplitString(file_extensions[i], ',', &mime_type.file_extensions); + + if (descriptions.size() > i) { + mime_type.description = descriptions[i]; + + // On Windows, the description likely has a list of file extensions + // embedded in it (e.g. "SurfWriter file (*.swr)"). Remove an extension + // list from the description if it is present. + size_t ext = mime_type.description.find(ASCIIToUTF16("(*")); + if (ext != string16::npos) { + if (ext > 1 && mime_type.description[ext -1] == ' ') + ext--; + + mime_type.description.erase(ext); + } + } + + info->mime_types.push_back(mime_type); + } + + return true; +} + +PluginList::PluginList() + : plugins_loaded_(false), + plugins_need_refresh_(false), + disable_outdated_plugins_(false), + next_priority_(0) { + PlatformInit(); + AddHardcodedPluginGroups(); +} + +bool PluginList::ShouldDisableGroup(const string16& group_name) { + AutoLock lock(lock_); + if (PluginGroup::IsPluginNameDisabledByPolicy(group_name)) { + disabled_groups_.insert(group_name); + return true; + } + return disabled_groups_.count(group_name) > 0; +} + +void PluginList::LoadPlugins(bool refresh) { + // Don't want to hold the lock while loading new plugins, so we don't block + // other methods if they're called on other threads. + std::vector extra_plugin_paths; + std::vector extra_plugin_dirs; + std::vector internal_plugins; + { + AutoLock lock(lock_); + if (plugins_loaded_ && !refresh && !plugins_need_refresh_) + return; + + // Clear the refresh bit now, because it might get set again before we + // reach the end of the method. + plugins_need_refresh_ = false; + extra_plugin_paths = extra_plugin_paths_; + extra_plugin_dirs = extra_plugin_dirs_; + internal_plugins = internal_plugins_; + } + + std::vector new_plugins; + std::set visited_plugins; + + std::vector directories_to_scan; + GetPluginDirectories(&directories_to_scan); + + // Load internal plugins first so that, if both an internal plugin and a + // "discovered" plugin want to handle the same type, the internal plugin + // will have precedence. + for (size_t i = 0; i < internal_plugins.size(); ++i) { + if (internal_plugins[i].path.value() == kDefaultPluginLibraryName) + continue; + LoadPlugin(internal_plugins[i].path, &new_plugins); + } + + for (size_t i = 0; i < extra_plugin_paths.size(); ++i) { + const FilePath& path = extra_plugin_paths[i]; + if (visited_plugins.find(path) != visited_plugins.end()) + continue; + LoadPlugin(path, &new_plugins); + visited_plugins.insert(path); + } + + for (size_t i = 0; i < extra_plugin_dirs.size(); ++i) { + LoadPluginsFromDir(extra_plugin_dirs[i], &new_plugins, &visited_plugins); + } + + for (size_t i = 0; i < directories_to_scan.size(); ++i) { + LoadPluginsFromDir(directories_to_scan[i], &new_plugins, &visited_plugins); + } + +#if defined(OS_WIN) + LoadPluginsFromRegistry(&new_plugins, &visited_plugins); +#endif + + // Load the default plugin last. + if (webkit_glue::IsDefaultPluginEnabled()) + LoadPlugin(FilePath(kDefaultPluginLibraryName), &new_plugins); + + // Disable all of the plugins and plugin groups that are disabled by policy. + // There's currenly a bug that makes it impossible to correctly re-enable + // plugins or plugin-groups to their original, "pre-policy" state, so + // plugins and groups are only changed to a more "safe" state after a policy + // change, i.e. from enabled to disabled. See bug 54681. + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + PluginGroup* group = it->second; + string16 group_name = group->GetGroupName(); + if (ShouldDisableGroup(group_name)) { + group->Enable(false); + } + + if (disable_outdated_plugins_) { + group->DisableOutdatedPlugins(); + } + if (!group->Enabled()) { + AutoLock lock(lock_); + disabled_groups_.insert(group_name); + } + } + + // Only update the data now since loading plugins can take a while. + AutoLock lock(lock_); + + plugins_ = new_plugins; + plugins_loaded_ = true; +} + +void PluginList::LoadPlugin(const FilePath& path, + std::vector* plugins) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Loading plugin " << path.value(); + + WebPluginInfo plugin_info; + const PluginEntryPoints* entry_points; + + if (!ReadPluginInfo(path, &plugin_info, &entry_points)) + return; + + if (!ShouldLoadPlugin(plugin_info, plugins)) + return; + + if (path.value() != kDefaultPluginLibraryName +#if defined(OS_WIN) && !defined(NDEBUG) + && path.BaseName().value() != L"npspy.dll" // Make an exception for NPSPY +#endif + ) { + for (size_t i = 0; i < plugin_info.mime_types.size(); ++i) { + // TODO: don't load global handlers for now. + // WebKit hands to the Plugin before it tries + // to handle mimeTypes on its own. + const std::string &mime_type = plugin_info.mime_types[i].mime_type; + if (mime_type == "*" ) + return; + } + } + + // Mark disabled plugins as such. (This has to happen before calling + // |AddToPluginGroups(plugin_info)|.) + if (disabled_plugins_.count(plugin_info.path)) { + plugin_info.enabled = false; + } else { + plugin_info.enabled = true; + } + + AutoLock lock(lock_); + plugins->push_back(plugin_info); + AddToPluginGroups(plugin_info); +} + +bool PluginList::SupportsType(const WebPluginInfo& info, + const std::string &mime_type, + bool allow_wildcard) { + // Webkit will ask for a plugin to handle empty mime types. + if (mime_type.empty()) + return false; + + for (size_t i = 0; i < info.mime_types.size(); ++i) { + const WebPluginMimeType& mime_info = info.mime_types[i]; + if (net::MatchesMimeType(mime_info.mime_type, mime_type)) { + if (!allow_wildcard && mime_info.mime_type == "*") { + continue; + } + return true; + } + } + return false; +} + +bool PluginList::SupportsExtension(const WebPluginInfo& info, + const std::string &extension, + std::string* actual_mime_type) { + for (size_t i = 0; i < info.mime_types.size(); ++i) { + const WebPluginMimeType& mime_type = info.mime_types[i]; + for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) { + if (mime_type.file_extensions[j] == extension) { + if (actual_mime_type) + *actual_mime_type = mime_type.mime_type; + return true; + } + } + } + + return false; +} + + +void PluginList::GetPlugins(bool refresh, std::vector* plugins) { + LoadPlugins(refresh); + + AutoLock lock(lock_); + *plugins = plugins_; +} + +void PluginList::GetEnabledPlugins(bool refresh, + std::vector* plugins) { + LoadPlugins(refresh); + + plugins->clear(); + AutoLock lock(lock_); + for (std::vector::const_iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->enabled) + plugins->push_back(*it); + } +} + +void PluginList::GetPluginInfoArray( + const GURL& url, + const std::string& mime_type, + bool allow_wildcard, + std::vector* info, + std::vector* actual_mime_types) { + DCHECK(mime_type == StringToLowerASCII(mime_type)); + DCHECK(info); + + LoadPlugins(false); + AutoLock lock(lock_); + info->clear(); + if (actual_mime_types) + actual_mime_types->clear(); + + std::set visited_plugins; + + // Add in enabled plugins by mime type. + WebPluginInfo default_plugin; + for (size_t i = 0; i < plugins_.size(); ++i) { + if (plugins_[i].enabled && + SupportsType(plugins_[i], mime_type, allow_wildcard)) { + FilePath path = plugins_[i].path; + if (path.value() != kDefaultPluginLibraryName && + visited_plugins.insert(path).second) { + info->push_back(plugins_[i]); + if (actual_mime_types) + actual_mime_types->push_back(mime_type); + } + } + } + + // Add in enabled plugins by url. + std::string path = url.path(); + std::string::size_type last_dot = path.rfind('.'); + if (last_dot != std::string::npos) { + std::string extension = StringToLowerASCII(std::string(path, last_dot+1)); + std::string actual_mime_type; + for (size_t i = 0; i < plugins_.size(); ++i) { + if (plugins_[i].enabled && + SupportsExtension(plugins_[i], extension, &actual_mime_type)) { + FilePath path = plugins_[i].path; + if (path.value() != kDefaultPluginLibraryName && + visited_plugins.insert(path).second) { + info->push_back(plugins_[i]); + if (actual_mime_types) + actual_mime_types->push_back(actual_mime_type); + } + } + } + } + + // Add in disabled plugins by mime type. + for (size_t i = 0; i < plugins_.size(); ++i) { + if (!plugins_[i].enabled && + SupportsType(plugins_[i], mime_type, allow_wildcard)) { + FilePath path = plugins_[i].path; + if (path.value() != kDefaultPluginLibraryName && + visited_plugins.insert(path).second) { + info->push_back(plugins_[i]); + if (actual_mime_types) + actual_mime_types->push_back(mime_type); + } + } + } + + // Add the default plugin at the end if it supports the mime type given, + // and the default plugin is enabled. + if (!plugins_.empty() && webkit_glue::IsDefaultPluginEnabled()) { + const WebPluginInfo& default_info = plugins_.back(); + if (SupportsType(default_info, mime_type, allow_wildcard)) { + info->push_back(default_info); + if (actual_mime_types) + actual_mime_types->push_back(mime_type); + } + } +} + +bool PluginList::GetPluginInfo(const GURL& url, + const std::string& mime_type, + bool allow_wildcard, + WebPluginInfo* info, + std::string* actual_mime_type) { + DCHECK(info); + std::vector info_list; + + // GetPluginInfoArray has slightly less work to do if we can pass + // NULL for the mime type list... + if (actual_mime_type) { + std::vector mime_type_list; + GetPluginInfoArray( + url, mime_type, allow_wildcard, &info_list, &mime_type_list); + if (!info_list.empty()) { + *info = info_list[0]; + *actual_mime_type = mime_type_list[0]; + return true; + } + } else { + GetPluginInfoArray(url, mime_type, allow_wildcard, &info_list, NULL); + if (!info_list.empty()) { + *info = info_list[0]; + return true; + } + } + return false; +} + +bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path, + WebPluginInfo* info) { + LoadPlugins(false); + AutoLock lock(lock_); + for (size_t i = 0; i < plugins_.size(); ++i) { + if (plugins_[i].path == plugin_path) { + *info = plugins_[i]; + return true; + } + } + + return false; +} + +void PluginList::GetPluginGroups( + bool load_if_necessary, + std::vector* plugin_groups) { + if (load_if_necessary) + LoadPlugins(false); + plugin_groups->clear(); + for (PluginGroup::PluginMap::const_iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + plugin_groups->push_back(*it->second); + } +} + +const PluginGroup* PluginList::GetPluginGroup( + const WebPluginInfo& web_plugin_info) { + AutoLock lock(lock_); + return AddToPluginGroups(web_plugin_info); +} + +string16 PluginList::GetPluginGroupName(std::string identifier) { + PluginGroup::PluginMap::iterator it = plugin_groups_.find(identifier); + if (it == plugin_groups_.end()) { + return string16(); + } + return it->second->GetGroupName(); +} + +std::string PluginList::GetPluginGroupIdentifier( + const WebPluginInfo& web_plugin_info) { + AutoLock lock(lock_); + PluginGroup* group = AddToPluginGroups(web_plugin_info); + return group->identifier(); +} + +void PluginList::AddHardcodedPluginGroups() { + AutoLock lock(lock_); + const PluginGroupDefinition* definitions = GetPluginGroupDefinitions(); + for (size_t i = 0; i < GetPluginGroupDefinitionsSize(); ++i) { + PluginGroup* definition_group = PluginGroup::FromPluginGroupDefinition( + definitions[i]); + std::string identifier = definition_group->identifier(); + DCHECK(plugin_groups_.find(identifier) == plugin_groups_.end()); + plugin_groups_.insert(std::make_pair(identifier, definition_group)); + } +} + +PluginGroup* PluginList::AddToPluginGroups( + const WebPluginInfo& web_plugin_info) { + PluginGroup* group = NULL; + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + if (it->second->Match(web_plugin_info)) + group = it->second; + } + if (!group) { + group = PluginGroup::FromWebPluginInfo(web_plugin_info); + std::string identifier = group->identifier(); + // If the identifier is not unique, use the full path. This means that we + // probably won't be able to search for this group by identifier, but at + // least it's going to be in the set of plugin groups, and if there + // is already a plug-in with the same filename, it's probably going to + // handle the same MIME types (and it has a higher priority), so this one + // is not going to run anyway. + if (plugin_groups_.find(identifier) != plugin_groups_.end()) + identifier = PluginGroup::GetLongIdentifier(web_plugin_info); + DCHECK(plugin_groups_.find(identifier) == plugin_groups_.end()); + plugin_groups_.insert(std::make_pair(identifier, group)); + } + group->AddPlugin(web_plugin_info, next_priority_++); + return group; +} + +bool PluginList::EnablePlugin(const FilePath& filename) { + AutoLock lock(lock_); + + bool did_enable = false; + + std::set::iterator entry = disabled_plugins_.find(filename); + if (entry == disabled_plugins_.end()) + return did_enable; // Early exit if plugin not in disabled list. + + disabled_plugins_.erase(entry); // Remove from disabled list. + + // Set enabled flags if necessary. + for (std::vector::iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->path == filename) { + DCHECK(!it->enabled); // Should have been disabled. + it->enabled = true; + did_enable = true; + } + } + + return did_enable; +} + +bool PluginList::DisablePlugin(const FilePath& filename) { + AutoLock lock(lock_); + + bool did_disable = false; + + if (disabled_plugins_.find(filename) != disabled_plugins_.end()) + return did_disable; // Early exit if plugin already in disabled list. + + disabled_plugins_.insert(filename); // Add to disabled list. + + // Unset enabled flags if necessary. + for (std::vector::iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->path == filename) { + DCHECK(it->enabled); // Should have been enabled. + it->enabled = false; + did_disable = true; + } + } + + return did_disable; +} + +bool PluginList::EnableGroup(bool enable, const string16& group_name) { + bool did_change = false; + { + AutoLock lock(lock_); + + std::set::iterator entry = disabled_groups_.find(group_name); + if (enable) { + if (entry == disabled_groups_.end()) + return did_change; // Early exit if group not in disabled list. + disabled_groups_.erase(entry); // Remove from disabled list. + } else { + if (entry != disabled_groups_.end()) + return did_change; // Early exit if group already in disabled list. + disabled_groups_.insert(group_name); + } + } + + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + if (it->second->GetGroupName() == group_name) { + if (it->second->Enabled() != enable) { + it->second->Enable(enable); + did_change = true; + break; + } + } + } + + return did_change; +} + +void PluginList::DisableOutdatedPluginGroups() { + disable_outdated_plugins_ = true; +} + +PluginList::~PluginList() { + Shutdown(); +} + +void PluginList::Shutdown() { + // TODO + // Note: plugin_groups_ contains simple pointers of type PluginGroup*, but + // since this singleton lives until the process is destroyed, no explicit + // cleanup is necessary. + // However, when running on Valgrind, we need to do the cleanup to keep the + // memory tree green. +#if defined(OS_POSIX) + if (RUNNING_ON_VALGRIND) { + STLDeleteContainerPairSecondPointers(plugin_groups_.begin(), + plugin_groups_.end()); + } +#endif +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index 111e8fa..734cc6d 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -5,26 +5,332 @@ #ifndef WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ #define WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ -// This file is here to keep NativeClient compiling. PluginList was moved to -// webkit/plugins/npapi and into the webkit::npapi namespace. Native Client -// depends on this old location & namespace, so we provide just enough -// definitions here to keep it compiling until it can be updated to use the -// new location & namespace. -// -// TODO(brettw) remove this flie when NaCl is updated. +#include +#include +#include -#include "webkit/plugins/npapi/plugin_list.h" +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/linked_ptr.h" +#include "base/lock.h" +#include "third_party/npapi/bindings/nphostapi.h" +#include "webkit/glue/plugins/plugin_group.h" +#include "webkit/glue/plugins/webplugininfo.h" + +class GURL; + +namespace base { + +template +struct DefaultLazyInstanceTraits; + +} // namespace base namespace NPAPI { -typedef webkit::npapi::PluginEntryPoints PluginEntryPoints; -typedef webkit::npapi::PluginVersionInfo PluginVersionInfo; +#define kDefaultPluginLibraryName FILE_PATH_LITERAL("default_plugin") +#define kGearsPluginLibraryName FILE_PATH_LITERAL("gears") + +class PluginInstance; + +// This struct holds entry points into a plugin. The entry points are +// slightly different between Win/Mac and Unixes. +struct PluginEntryPoints { +#if !defined(OS_POSIX) || defined(OS_MACOSX) + NP_GetEntryPointsFunc np_getentrypoints; +#endif + NP_InitializeFunc np_initialize; + NP_ShutdownFunc np_shutdown; +}; + +// This struct fully describes a plugin. For external plugins, it's read in from +// the version info of the dll; For internal plugins, it's predefined and +// includes addresses of entry functions. (Yes, it's Win32 NPAPI-centric, but +// it'll do for holding descriptions of internal plugins cross-platform.) +struct PluginVersionInfo { + FilePath path; + // Info about the plugin itself. + std::wstring product_name; + std::wstring file_description; + std::wstring file_version; + // Info about the data types that the plugin supports. + std::wstring mime_types; + std::wstring file_extensions; + std::wstring type_descriptions; + // Entry points for internal plugins. Pointers are NULL for external plugins. + PluginEntryPoints entry_points; +}; +// The PluginList is responsible for loading our NPAPI based plugins. It does +// so in whatever manner is appropriate for the platform. On Windows, it loads +// plugins from a known directory by looking for DLLs which start with "NP", +// and checking to see if they are valid NPAPI libraries. On the Mac, it walks +// the machine-wide and user plugin directories and loads anything that has +// the correct types. On Linux, it walks the plugin directories as well +// (e.g. /usr/lib/browser-plugins/). +// This object is thread safe. class PluginList { public: - static inline webkit::npapi::PluginList* Singleton() { - return webkit::npapi::PluginList::Singleton(); - } + // Gets the one instance of the PluginList. + static PluginList* Singleton(); + + // Returns true if we're in debug-plugin-loading mode. This is controlled + // by a command line switch. + static bool DebugPluginLoading(); + + static const PluginGroupDefinition* GetPluginGroupDefinitions(); + static size_t GetPluginGroupDefinitionsSize(); + + // Returns true iff the plugin list has been loaded already. + bool PluginsLoaded(); + + // Cause the plugin list to refresh next time they are accessed, regardless + // of whether they are already loaded. + void RefreshPlugins(); + + // Add/Remove an extra plugin to load when we actually do the loading. Must + // be called before the plugins have been loaded. + void AddExtraPluginPath(const FilePath& plugin_path); + void RemoveExtraPluginPath(const FilePath& plugin_path); + + // Same as above, but specifies a directory in which to search for plugins. + void AddExtraPluginDir(const FilePath& plugin_dir); + + // Register an internal plugin with the specified plugin information and + // function pointers. An internal plugin must be registered before it can + // be loaded using PluginList::LoadPlugin(). + void RegisterInternalPlugin(const PluginVersionInfo& info); + + // Removes a specified internal plugin from the list. The search will match + // on the path from the version info previously registered. + // + // This is generally only necessary for tests. + void UnregisterInternalPlugin(const FilePath& path); + + // Creates a WebPluginInfo structure given a plugin's path. On success + // returns true, with the information being put into "info". If it's an + // internal plugin, "entry_points" is filled in as well with a + // internally-owned PluginEntryPoints pointer. + // Returns false if the library couldn't be found, or if it's not a plugin. + bool ReadPluginInfo(const FilePath& filename, + WebPluginInfo* info, + const PluginEntryPoints** entry_points); + + // Populate a WebPluginInfo from a PluginVersionInfo. + static bool CreateWebPluginInfo(const PluginVersionInfo& pvi, + WebPluginInfo* info); + + // Shutdown all plugins. Should be called at process teardown. + void Shutdown(); + + // Get all the plugins. + void GetPlugins(bool refresh, std::vector* plugins); + + // Get all the enabled plugins. + void GetEnabledPlugins(bool refresh, std::vector* plugins); + + // Returns a list in |info| containing plugins that are found for + // the given url and mime type (including disabled plugins, for + // which |info->enabled| is false). The mime type which corresponds + // to the URL is optionally returned back in |actual_mime_types| (if + // it is non-NULL), one for each of the plugin info objects found. + // The |allow_wildcard| parameter controls whether this function + // returns plugins which support wildcard mime types (* as the mime + // type). The |info| parameter is required to be non-NULL. The + // list is in order of "most desirable" to "least desirable", + // meaning that the default plugin is at the end of the list. + void GetPluginInfoArray(const GURL& url, + const std::string& mime_type, + bool allow_wildcard, + std::vector* info, + std::vector* actual_mime_types); + + // Returns the first item from the list returned in GetPluginInfo in |info|. + // Returns true if it found a match. |actual_mime_type| may be NULL. + bool GetPluginInfo(const GURL& url, + const std::string& mime_type, + bool allow_wildcard, + WebPluginInfo* info, + std::string* actual_mime_type); + + // Get plugin info by plugin path (including disabled plugins). Returns true + // if the plugin is found and WebPluginInfo has been filled in |info|. + bool GetPluginInfoByPath(const FilePath& plugin_path, + WebPluginInfo* info); + + // Populates the given vector with all available plugin groups. + void GetPluginGroups(bool load_if_necessary, + std::vector* plugin_groups); + + // Returns the PluginGroup corresponding to the given WebPluginInfo. If no + // such group exists, it is created and added to the cache. + // Beware: when calling this from the Browser process, the group that the + // returned pointer points to might disappear suddenly. This happens when + // |RefreshPlugins()| is called and then |LoadPlugins()| is triggered by a + // call to |GetPlugins()|, |GetEnabledPlugins()|, |GetPluginInfoArray()|, + // |GetPluginInfoByPath()|, or |GetPluginGroups(true, _)|. It is the caller's + // responsibility to make sure this doesn't happen. + const PluginGroup* GetPluginGroup(const WebPluginInfo& web_plugin_info); + + // Returns the name of the PluginGroup with the given identifier. + // If no such group exists, an empty string is returned. + string16 GetPluginGroupName(std::string identifier); + + // Returns the identifier string of the PluginGroup corresponding to the given + // WebPluginInfo. If no such group exists, it is created and added to the + // cache. + std::string GetPluginGroupIdentifier(const WebPluginInfo& web_plugin_info); + + // Load a specific plugin with full path. + void LoadPlugin(const FilePath& filename, + std::vector* plugins); + + // Enable a specific plugin, specified by path. Returns |true| iff a plugin + // currently in the plugin list was actually enabled as a result; regardless + // of return value, if a plugin is found in the future with the given name, it + // will be enabled. Note that plugins are enabled by default as far as + // |PluginList| is concerned. + bool EnablePlugin(const FilePath& filename); + + // Disable a specific plugin, specified by path. Returns |true| iff a plugin + // currently in the plugin list was actually disabled as a result; regardless + // of return value, if a plugin is found in the future with the given name, it + // will be disabled. + bool DisablePlugin(const FilePath& filename); + + // Enable/disable a plugin group, specified by group_name. Returns |true| iff + // a plugin currently in the plugin list was actually enabled/disabled as a + // result; regardless of return value, if a plugin is found in the future with + // the given name, it will be enabled/disabled. Note that plugins are enabled + // by default as far as |PluginList| is concerned. + bool EnableGroup(bool enable, const string16& name); + + // Disable all plugins groups that are known to be outdated, according to + // the information hardcoded in PluginGroup, to make sure that they can't + // be loaded on a web page and instead show a UI to update to the latest + // version. + void DisableOutdatedPluginGroups(); + + ~PluginList(); + + private: + FRIEND_TEST_ALL_PREFIXES(PluginGroupTest, PluginGroupDefinition); + + // Constructors are private for singletons + PluginList(); + + // Creates PluginGroups for the static group definitions, and adds them to + // the PluginGroup cache of this PluginList. + void AddHardcodedPluginGroups(); + + // Adds the given WebPluginInfo to its corresponding group, creating it if + // necessary, and returns the group. + // Callers need to protect calls to this method by a lock themselves. + PluginGroup* AddToPluginGroups(const WebPluginInfo& web_plugin_info); + + // Load all plugins from the default plugins directory + void LoadPlugins(bool refresh); + + // Load all plugins from a specific directory. + // |plugins| is updated with loaded plugin information. + // |visited_plugins| is updated with paths to all plugins that were considered + // (including those we didn't load) + void LoadPluginsFromDir(const FilePath& path, + std::vector* plugins, + std::set* visited_plugins); + + // Returns true if we should load the given plugin, or false otherwise. + // plugins is the list of plugins we have crawled in the current plugin + // loading run. + bool ShouldLoadPlugin(const WebPluginInfo& info, + std::vector* plugins); + + // Return whether a plug-in group with the given name should be disabled, + // either because it already is on the list of disabled groups, or because it + // is blacklisted by a policy. In the latter case, add the plugin group to the + // list of disabled groups as well. + bool ShouldDisableGroup(const string16& group_name); + + // Returns true if the given WebPluginInfo supports "mime-type". + // mime_type should be all lower case. + static bool SupportsType(const WebPluginInfo& info, + const std::string &mime_type, + bool allow_wildcard); + + // Returns true if the given WebPluginInfo supports a given file extension. + // extension should be all lower case. + // If mime_type is not NULL, it will be set to the mime type if found. + // The mime type which corresponds to the extension is optionally returned + // back. + static bool SupportsExtension(const WebPluginInfo& info, + const std::string &extension, + std::string* actual_mime_type); + + // + // Platform functions + // + + // Do any initialization. + void PlatformInit(); + + // Get the ordered list of directories from which to load plugins + void GetPluginDirectories(std::vector* plugin_dirs); + + // + // Command-line switches + // + +#if defined(OS_WIN) + // true if we shouldn't load the new WMP plugin. + bool dont_load_new_wmp_; + + // Loads plugins registered under HKCU\Software\MozillaPlugins and + // HKLM\Software\MozillaPlugins. + void LoadPluginsFromRegistry(std::vector* plugins, + std::set* visited_plugins); +#endif + + // + // Internals + // + + bool plugins_loaded_; + + // If true, we reload plugins even if they've been loaded already. + bool plugins_need_refresh_; + + // Contains information about the available plugins. + std::vector plugins_; + + // Extra plugin paths that we want to search when loading. + std::vector extra_plugin_paths_; + + // Extra plugin directories that we want to search when loading. + std::vector extra_plugin_dirs_; + + // Holds information about internal plugins. + std::vector internal_plugins_; + + // Path names of plugins to disable (the default is to enable them all). + std::set disabled_plugins_; + + // Group names to disable (the default is to enable them all). + std::set disabled_groups_; + + bool disable_outdated_plugins_; + + // Holds the currently available plugin groups. + PluginGroup::PluginMap plugin_groups_; + + int next_priority_; + + // Need synchronization for the above members since this object can be + // accessed on multiple threads. + Lock lock_; + + friend struct base::DefaultLazyInstanceTraits; + + DISALLOW_COPY_AND_ASSIGN(PluginList); }; } // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list_mac.mm b/webkit/glue/plugins/plugin_list_mac.mm new file mode 100644 index 0000000..e7a2337 --- /dev/null +++ b/webkit/glue/plugins/plugin_list_mac.mm @@ -0,0 +1,109 @@ +// Copyright (c) 2006-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 "webkit/glue/plugins/plugin_list.h" + +#import + +#include "base/file_util.h" +#include "base/mac_util.h" +#include "base/string_number_conversions.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "webkit/glue/plugins/plugin_lib.h" + +namespace { + +void GetPluginCommonDirectory(std::vector* plugin_dirs, + bool user) { + // Note that there are no NSSearchPathDirectory constants for these + // directories so we can't use Cocoa's NSSearchPathForDirectoriesInDomains(). + // Interestingly, Safari hard-codes the location (see + // WebKit/WebKit/mac/Plugins/WebPluginDatabase.mm's +_defaultPlugInPaths). + FSRef ref; + OSErr err = FSFindFolder(user ? kUserDomain : kLocalDomain, + kInternetPlugInFolderType, false, &ref); + + if (err) + return; + + plugin_dirs->push_back(FilePath(mac_util::PathFromFSRef(ref))); +} + +// Returns true if the plugin should be prevented from loading. +bool IsBlacklistedPlugin(const WebPluginInfo& info) { + // We blacklist Gears by included MIME type, since that is more stable than + // its name. Be careful about adding any more plugins to this list though, + // since it's easy to accidentally blacklist plugins that support lots of + // MIME types. + for (std::vector::const_iterator i = + info.mime_types.begin(); i != info.mime_types.end(); ++i) { + // The Gears plugin is Safari-specific, so don't load it. + if (i->mime_type == "application/x-googlegears") + return true; + } + + // Versions of Flip4Mac 2.3 before 2.3.6 often hang the renderer, so don't + // load them. + if (StartsWith(info.name, ASCIIToUTF16("Flip4Mac Windows Media"), false) && + StartsWith(info.version, ASCIIToUTF16("2.3"), false)) { + std::vector components; + base::SplitString(info.version, '.', &components); + int bugfix_version = 0; + return (components.size() >= 3 && + base::StringToInt(components[2], &bugfix_version) && + bugfix_version < 6); + } + + return false; +} + +} // namespace + +namespace NPAPI +{ + +void PluginList::PlatformInit() { +} + +void PluginList::GetPluginDirectories(std::vector* plugin_dirs) { + // Load from the user's area + GetPluginCommonDirectory(plugin_dirs, true); + + // Load from the machine-wide area + GetPluginCommonDirectory(plugin_dirs, false); +} + +void PluginList::LoadPluginsFromDir(const FilePath &path, + std::vector* plugins, + std::set* visited_plugins) { + file_util::FileEnumerator enumerator(path, + false, // not recursive + file_util::FileEnumerator::DIRECTORIES); + for (FilePath path = enumerator.Next(); !path.value().empty(); + path = enumerator.Next()) { + LoadPlugin(path, plugins); + visited_plugins->insert(path); + } +} + +bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, + std::vector* plugins) { + if (IsBlacklistedPlugin(info)) + return false; + + // Hierarchy check + // (we're loading plugins hierarchically from Library folders, so plugins we + // encounter earlier must override plugins we encounter later) + for (size_t i = 0; i < plugins->size(); ++i) { + if ((*plugins)[i].path.BaseName() == info.path.BaseName()) { + return false; // We already have a loaded plugin higher in the hierarchy. + } + } + + return true; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list_posix.cc b/webkit/glue/plugins/plugin_list_posix.cc new file mode 100644 index 0000000..654c0c5 --- /dev/null +++ b/webkit/glue/plugins/plugin_list_posix.cc @@ -0,0 +1,270 @@ +// 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 "webkit/glue/plugins/plugin_list.h" + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/sha1.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "build/build_config.h" + +namespace { + +// We build up a list of files and mtimes so we can sort them. +typedef std::pair FileAndTime; +typedef std::vector FileTimeList; + +// Comparator used to sort by descending mtime then ascending filename. +bool CompareTime(const FileAndTime& a, const FileAndTime& b) { + if (a.second == b.second) { + // Fall back on filename sorting, just to make the predicate valid. + return a.first < b.first; + } + + // Sort by mtime, descending. + return a.second > b.second; +} + +// Return true if |path| matches a known (file size, sha1sum) pair. +// The use of the file size is an optimization so we don't have to read in +// the entire file unless we have to. +bool IsBlacklistedBySha1sum(const FilePath& path) { + const struct BadEntry { + int64 size; + std::string sha1; + } bad_entries[] = { + // Flash 9 r31 - http://crbug.com/29237 + { 7040080, "fa5803061125ca47846713b34a26a42f1f1e98bb" }, + // Flash 9 r48 - http://crbug.com/29237 + { 7040036, "0c4b3768a6d4bfba003088e4b9090d381de1af2b" }, + }; + + int64 size; + if (!file_util::GetFileSize(path, &size)) + return false; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(bad_entries); i++) { + if (bad_entries[i].size != size) + continue; + + std::string file_content; + if (!file_util::ReadFileToString(path, &file_content)) + continue; + std::string sha1 = base::SHA1HashString(file_content); + std::string sha1_readable; + for (size_t j = 0; j < sha1.size(); j++) + base::StringAppendF(&sha1_readable, "%02x", sha1[j] & 0xFF); + if (bad_entries[i].sha1 == sha1_readable) + return true; + } + return false; +} + +// Some plugins are shells around other plugins; we prefer to use the +// real plugin directly, if it's available. This function returns +// true if we should prefer other plugins over this one. We'll still +// use a "undesirable" plugin if no other option is available. +bool IsUndesirablePlugin(const WebPluginInfo& info) { + std::string filename = info.path.BaseName().value(); + const char* kUndesiredPlugins[] = { + "npcxoffice", // Crossover + "npwrapper", // nspluginwrapper + }; + for (size_t i = 0; i < arraysize(kUndesiredPlugins); i++) { + if (filename.find(kUndesiredPlugins[i]) != std::string::npos) { + return true; + } + } + return false; +} + +// Return true if we shouldn't load a plugin at all. +// This is an ugly hack to blacklist Adobe Acrobat due to not supporting +// its Xt-based mainloop. +// http://code.google.com/p/chromium/issues/detail?id=38229 +// The gecko-mediaplayer plugins also crashes the entire browser sometimes. +// http://code.google.com/p/chromium/issues/detail?id=24507 +bool IsBlacklistedPlugin(const FilePath& path) { + const char* kBlackListedPlugins[] = { + "nppdf.so", // Adobe PDF + "gecko-mediaplayer", // Gecko Media Player + }; + std::string filename = path.BaseName().value(); + for (size_t i = 0; i < arraysize(kBlackListedPlugins); i++) { + if (filename.find(kBlackListedPlugins[i]) != std::string::npos) { + return true; + } + } + return IsBlacklistedBySha1sum(path); +} + +} // anonymous namespace + +namespace NPAPI { + +void PluginList::PlatformInit() { +} + +void PluginList::GetPluginDirectories(std::vector* plugin_dirs) { + // See http://groups.google.com/group/chromium-dev/browse_thread/thread/7a70e5fcbac786a9 + // for discussion. + // We first consult Chrome-specific dirs, then fall back on the logic + // Mozilla uses. + + // Note: "extra" plugin dirs, including the Plugins subdirectory of + // your Chrome config, are examined before these. See the logic + // related to extra_plugin_dirs in plugin_list.cc. + + // The Chrome binary dir + "plugins/". + FilePath dir; + PathService::Get(base::DIR_EXE, &dir); + plugin_dirs->push_back(dir.Append("plugins")); + + // Chrome OS only loads plugins from /opt/google/chrome/plugins. +#if !defined(OS_CHROMEOS) + // Mozilla code to reference: + // http://mxr.mozilla.org/firefox/ident?i=NS_APP_PLUGINS_DIR_LIST + // and tens of accompanying files (mxr is very helpful). + // This code carefully matches their behavior for compat reasons. + + // 1) MOZ_PLUGIN_PATH env variable. + const char* moz_plugin_path = getenv("MOZ_PLUGIN_PATH"); + if (moz_plugin_path) { + std::vector paths; + base::SplitString(moz_plugin_path, ':', &paths); + for (size_t i = 0; i < paths.size(); ++i) + plugin_dirs->push_back(FilePath(paths[i])); + } + + // 2) NS_USER_PLUGINS_DIR: ~/.mozilla/plugins. + // This is a de-facto standard, so even though we're not Mozilla, let's + // look in there too. + FilePath home = file_util::GetHomeDir(); + if (!home.empty()) + plugin_dirs->push_back(home.Append(".mozilla/plugins")); + + // 3) NS_SYSTEM_PLUGINS_DIR: + // This varies across different browsers and versions, so check 'em all. + plugin_dirs->push_back(FilePath("/usr/lib/browser-plugins")); + plugin_dirs->push_back(FilePath("/usr/lib/mozilla/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib/firefox/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib/xulrunner-addons/plugins")); + +#if defined(ARCH_CPU_64_BITS) + // On my Ubuntu system, /usr/lib64 is a symlink to /usr/lib. + // But a user reported on their Fedora system they are separate. + plugin_dirs->push_back(FilePath("/usr/lib64/browser-plugins")); + plugin_dirs->push_back(FilePath("/usr/lib64/mozilla/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib64/firefox/plugins")); + plugin_dirs->push_back(FilePath("/usr/lib64/xulrunner-addons/plugins")); +#endif // defined(ARCH_CPU_64_BITS) +#endif // !defined(OS_CHROMEOS) +} + +void PluginList::LoadPluginsFromDir(const FilePath& dir_path, + std::vector* plugins, + std::set* visited_plugins) { + // See ScanPluginsDirectory near + // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginHostImpl.cpp#5052 + + // Construct and stat a list of all filenames under consideration, for + // later sorting by mtime. + FileTimeList files; + file_util::FileEnumerator enumerator(dir_path, + false, // not recursive + file_util::FileEnumerator::FILES); + for (FilePath path = enumerator.Next(); !path.value().empty(); + path = enumerator.Next()) { + // Skip over Mozilla .xpt files. + if (path.MatchesExtension(FILE_PATH_LITERAL(".xpt"))) + continue; + + // Java doesn't like being loaded through a symlink, since it uses + // its path to find dependent data files. + // file_util::AbsolutePath calls through to realpath(), which resolves + // symlinks. + FilePath orig_path = path; + file_util::AbsolutePath(&path); + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Resolved " << orig_path.value() << " -> " << path.value(); + + if (visited_plugins->find(path) != visited_plugins->end()) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Skipping duplicate instance of " << path.value(); + continue; + } + visited_plugins->insert(path); + + if (IsBlacklistedPlugin(path)) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Skipping blacklisted plugin " << path.value(); + continue; + } + + // Flash stops working if the containing directory involves 'netscape'. + // No joke. So use the other path if it's better. + static const char kFlashPlayerFilename[] = "libflashplayer.so"; + static const char kNetscapeInPath[] = "/netscape/"; + if (path.BaseName().value() == kFlashPlayerFilename && + path.value().find(kNetscapeInPath) != std::string::npos) { + if (orig_path.value().find(kNetscapeInPath) == std::string::npos) { + // Go back to the old path. + path = orig_path; + } else { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Flash misbehaves when used from a directory containing " + << kNetscapeInPath << ", so skipping " << orig_path.value(); + continue; + } + } + + // Get mtime. + base::PlatformFileInfo info; + if (!file_util::GetFileInfo(path, &info)) + continue; + + files.push_back(std::make_pair(path, info.last_modified)); + } + + // Sort the file list by time (and filename). + std::sort(files.begin(), files.end(), CompareTime); + + // Load the files in order. + for (FileTimeList::const_iterator i = files.begin(); i != files.end(); ++i) { + LoadPlugin(i->first, plugins); + } +} + +bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, + std::vector* plugins) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Considering " << info.path.value() << " (" << info.name << ")"; + + if (IsUndesirablePlugin(info)) { + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << info.path.value() << " is undesirable."; + + // See if we have a better version of this plugin. + for (size_t i = 0; i < plugins->size(); ++i) { + if (plugins->at(i).name == info.name && + !IsUndesirablePlugin(plugins->at(i))) { + // Skip the current undesirable one so we can use the better one + // we just found. + LOG_IF(ERROR, PluginList::DebugPluginLoading()) + << "Skipping " << info.path.value() << ", preferring " + << plugins->at(i).path.value(); + return false; + } + } + } + + // TODO(evanm): prefer the newest version of flash, etc. here? + + VLOG_IF(1, PluginList::DebugPluginLoading()) << "Using " << info.path.value(); + + return true; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list_win.cc b/webkit/glue/plugins/plugin_list_win.cc new file mode 100644 index 0000000..4869262 --- /dev/null +++ b/webkit/glue/plugins/plugin_list_win.cc @@ -0,0 +1,410 @@ +// 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 "webkit/glue/plugins/plugin_list.h" + +#include + +#include + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/win/registry.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/webkit_glue.h" + +namespace { + +const TCHAR kRegistryApps[] = + _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"); +const TCHAR kRegistryFirefox[] = _T("firefox.exe"); +const TCHAR kRegistryAcrobat[] = _T("Acrobat.exe"); +const TCHAR kRegistryAcrobatReader[] = _T("AcroRd32.exe"); +const TCHAR kRegistryWindowsMedia[] = _T("wmplayer.exe"); +const TCHAR kRegistryQuickTime[] = _T("QuickTimePlayer.exe"); +const TCHAR kRegistryPath[] = _T("Path"); +const TCHAR kRegistryFirefoxInstalled[] = + _T("SOFTWARE\\Mozilla\\Mozilla Firefox"); +const TCHAR kRegistryJava[] = + _T("Software\\JavaSoft\\Java Runtime Environment"); +const TCHAR kRegistryBrowserJavaVersion[] = _T("BrowserJavaVersion"); +const TCHAR kRegistryCurrentJavaVersion[] = _T("CurrentVersion"); +const TCHAR kRegistryJavaHome[] = _T("JavaHome"); +const TCHAR kJavaDeploy1[] = _T("npdeploytk.dll"); +const TCHAR kJavaDeploy2[] = _T("npdeployjava1.dll"); + +// The application path where we expect to find plugins. +void GetAppDirectory(std::set* plugin_dirs) { + FilePath app_path; + if (!webkit_glue::GetApplicationDirectory(&app_path)) + return; + + app_path = app_path.AppendASCII("plugins"); + plugin_dirs->insert(app_path); +} + +// The executable path where we expect to find plugins. +void GetExeDirectory(std::set* plugin_dirs) { + FilePath exe_path; + if (!webkit_glue::GetExeDirectory(&exe_path)) + return; + + exe_path = exe_path.AppendASCII("plugins"); + plugin_dirs->insert(exe_path); +} + +// Gets the installed path for a registered app. +bool GetInstalledPath(const TCHAR* app, FilePath* out) { + std::wstring reg_path(kRegistryApps); + reg_path.append(L"\\"); + reg_path.append(app); + + base::win::RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ); + std::wstring path; + if (key.ReadValue(kRegistryPath, &path)) { + *out = FilePath(path); + return true; + } + + return false; +} + +// Search the registry at the given path and detect plugin directories. +void GetPluginsInRegistryDirectory( + HKEY root_key, + const std::wstring& registry_folder, + std::set* plugin_dirs) { + for (base::win::RegistryKeyIterator iter(root_key, registry_folder.c_str()); + iter.Valid(); ++iter) { + // Use the registry to gather plugin across the file system. + std::wstring 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); + + std::wstring path; + if (key.ReadValue(kRegistryPath, &path)) + plugin_dirs->insert(FilePath(path)); + } +} + +// Enumerate through the registry key to find all installed FireFox paths. +// FireFox 3 beta and version 2 can coexist. See bug: 1025003 +void GetFirefoxInstalledPaths(std::vector* out) { + base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, + kRegistryFirefoxInstalled); + for (; it.Valid(); ++it) { + std::wstring full_path = std::wstring(kRegistryFirefoxInstalled) + L"\\" + + it.Name() + L"\\Main"; + base::win::RegKey key(HKEY_LOCAL_MACHINE, full_path.c_str(), KEY_READ); + std::wstring install_dir; + if (!key.ReadValue(L"Install Directory", &install_dir)) + continue; + out->push_back(FilePath(install_dir)); + } +} + +// Get plugin directory locations from the Firefox install path. This is kind +// of a kludge, but it helps us locate the flash player for users that +// already have it for firefox. Not having to download yet-another-plugin +// is a good thing. +void GetFirefoxDirectory(std::set* plugin_dirs) { + std::vector paths; + GetFirefoxInstalledPaths(&paths); + for (unsigned int i = 0; i < paths.size(); ++i) { + plugin_dirs->insert(paths[i].Append(L"plugins")); + } + + FilePath firefox_app_data_plugin_path; + if (PathService::Get(base::DIR_APP_DATA, &firefox_app_data_plugin_path)) { + firefox_app_data_plugin_path = + firefox_app_data_plugin_path.AppendASCII("Mozilla") + .AppendASCII("plugins"); + plugin_dirs->insert(firefox_app_data_plugin_path); + } +} + +// Hardcoded logic to detect Acrobat plugins locations. +void GetAcrobatDirectory(std::set* plugin_dirs) { + FilePath path; + if (!GetInstalledPath(kRegistryAcrobatReader, &path) && + !GetInstalledPath(kRegistryAcrobat, &path)) { + return; + } + + plugin_dirs->insert(path.Append(L"Browser")); +} + +// Hardcoded logic to detect QuickTime plugin location. +void GetQuicktimeDirectory(std::set* plugin_dirs) { + FilePath path; + if (GetInstalledPath(kRegistryQuickTime, &path)) + plugin_dirs->insert(path.Append(L"plugins")); +} + +// Hardcoded logic to detect Windows Media Player plugin location. +void GetWindowsMediaDirectory(std::set* plugin_dirs) { + FilePath path; + if (GetInstalledPath(kRegistryWindowsMedia, &path)) + plugin_dirs->insert(path); + + // If the Windows Media Player Firefox plugin is installed before Firefox, + // the plugin will get written under PFiles\Plugins on one the drives + // (usually, but not always, the last letter). + int size = GetLogicalDriveStrings(0, NULL); + if (size) { + scoped_array strings(new wchar_t[size]); + if (GetLogicalDriveStrings(size, strings.get())) { + wchar_t* next_drive = strings.get(); + while (*next_drive) { + if (GetDriveType(next_drive) == DRIVE_FIXED) { + FilePath pfiles(next_drive); + pfiles = pfiles.Append(L"PFiles\\Plugins"); + if (file_util::PathExists(pfiles)) + plugin_dirs->insert(pfiles); + } + next_drive = &next_drive[wcslen(next_drive) + 1]; + } + } + } +} + +// Hardcoded logic to detect Java plugin location. +void GetJavaDirectory(std::set* plugin_dirs) { + // Load the new NPAPI Java plugin + // 1. Open the main JRE key under HKLM + base::win::RegKey java_key(HKEY_LOCAL_MACHINE, kRegistryJava, + KEY_QUERY_VALUE); + + // 2. Read the current Java version + std::wstring java_version; + if (!java_key.ReadValue(kRegistryBrowserJavaVersion, &java_version)) + java_key.ReadValue(kRegistryCurrentJavaVersion, &java_version); + + if (!java_version.empty()) { + java_key.OpenKey(java_version.c_str(), KEY_QUERY_VALUE); + + // 3. Install path of the JRE binaries is specified in "JavaHome" + // value under the Java version key. + std::wstring java_plugin_directory; + if (java_key.ReadValue(kRegistryJavaHome, &java_plugin_directory)) { + // 4. The new plugin resides under the 'bin/new_plugin' + // subdirectory. + DCHECK(!java_plugin_directory.empty()); + java_plugin_directory.append(L"\\bin\\new_plugin"); + + // 5. We don't know the exact name of the DLL but it's in the form + // NP*.dll so just invoke LoadPlugins on this path. + plugin_dirs->insert(FilePath(java_plugin_directory)); + } + } +} + +} // anonymous namespace + +namespace NPAPI { + +void PluginList::PlatformInit() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + dont_load_new_wmp_ = command_line.HasSwitch(kUseOldWMPPluginSwitch); +} + +void PluginList::GetPluginDirectories(std::vector* plugin_dirs) { + // We use a set for uniqueness, which we require, over order, which we do not. + std::set dirs; + + // Load from the application-specific area + GetAppDirectory(&dirs); + + // Load from the executable area + GetExeDirectory(&dirs); + + // Load Java + GetJavaDirectory(&dirs); + + // Load firefox plugins too. This is mainly to try to locate + // a pre-installed Flash player. + GetFirefoxDirectory(&dirs); + + // Firefox hard-codes the paths of some popular plugins to ensure that + // the plugins are found. We are going to copy this as well. + GetAcrobatDirectory(&dirs); + GetQuicktimeDirectory(&dirs); + GetWindowsMediaDirectory(&dirs); + + for (std::set::iterator i = dirs.begin(); i != dirs.end(); ++i) + plugin_dirs->push_back(*i); +} + +void PluginList::LoadPluginsFromDir(const FilePath &path, + std::vector* plugins, + std::set* visited_plugins) { + WIN32_FIND_DATA find_file_data; + HANDLE find_handle; + + std::wstring dir = path.value(); + // FindFirstFile requires that you specify a wildcard for directories. + dir.append(L"\\NP*.DLL"); + + find_handle = FindFirstFile(dir.c_str(), &find_file_data); + if (find_handle == INVALID_HANDLE_VALUE) + return; + + do { + if (!(find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + FilePath filename = path.Append(find_file_data.cFileName); + LoadPlugin(filename, plugins); + visited_plugins->insert(filename); + } + } while (FindNextFile(find_handle, &find_file_data) != 0); + + DCHECK(GetLastError() == ERROR_NO_MORE_FILES); + FindClose(find_handle); +} + +void PluginList::LoadPluginsFromRegistry( + std::vector* plugins, + std::set* visited_plugins) { + std::set plugin_dirs; + + GetPluginsInRegistryDirectory( + HKEY_CURRENT_USER, kRegistryMozillaPlugins, &plugin_dirs); + GetPluginsInRegistryDirectory( + HKEY_LOCAL_MACHINE, kRegistryMozillaPlugins, &plugin_dirs); + + for (std::set::iterator i = plugin_dirs.begin(); + i != plugin_dirs.end(); ++i) { + LoadPlugin(*i, plugins); + visited_plugins->insert(*i); + } +} + +// Returns true if the given plugins share at least one mime type. This is used +// to differentiate newer versions of a plugin vs two plugins which happen to +// have the same filename. +bool HaveSharedMimeType(const WebPluginInfo& plugin1, + const WebPluginInfo& plugin2) { + for (size_t i = 0; i < plugin1.mime_types.size(); ++i) { + for (size_t j = 0; j < plugin2.mime_types.size(); ++j) { + if (plugin1.mime_types[i].mime_type == plugin2.mime_types[j].mime_type) + return true; + } + } + + return false; +} + +// Compares Windows style version strings (i.e. 1,2,3,4). Returns true if b's +// version is newer than a's, or false if it's equal or older. +bool IsNewerVersion(const std::wstring& a, const std::wstring& b) { + std::vector a_ver, b_ver; + base::SplitString(a, ',', &a_ver); + base::SplitString(b, ',', &b_ver); + if (a_ver.size() == 1 && b_ver.size() == 1) { + a_ver.clear(); + b_ver.clear(); + base::SplitString(a, '.', &a_ver); + base::SplitString(b, '.', &b_ver); + } + if (a_ver.size() != b_ver.size()) + return false; + for (size_t i = 0; i < a_ver.size(); i++) { + int cur_a, cur_b; + base::StringToInt(a_ver[i], &cur_a); + base::StringToInt(b_ver[i], &cur_b); + + if (cur_a > cur_b) + return false; + if (cur_a < cur_b) + return true; + } + return false; +} + +bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info, + std::vector* plugins) { + // Version check + + for (size_t i = 0; i < plugins->size(); ++i) { + std::wstring plugin1 = + StringToLowerASCII((*plugins)[i].path.BaseName().ToWStringHack()); + std::wstring plugin2 = + StringToLowerASCII(info.path.BaseName().ToWStringHack()); + if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[i], info)) || + (plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) || + (plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) { + if (!IsNewerVersion((*plugins)[i].version, info.version)) + return false; // We have loaded a plugin whose version is newer. + + plugins->erase(plugins->begin() + i); + break; + } + } + + // Troublemakers + + std::wstring filename = StringToLowerASCII(info.path.BaseName().value()); + // Depends on XPCOM. + if (filename == kMozillaActiveXPlugin) + return false; + + // Disable the Yahoo Application State plugin as it crashes the plugin + // process on return from NPObjectStub::OnInvoke. Please refer to + // http://b/issue?id=1372124 for more information. + if (filename == kYahooApplicationStatePlugin) + return false; + + // Disable the WangWang protocol handler plugin (npww.dll) as it crashes + // chrome during shutdown. Firefox also disables this plugin. + // Please refer to http://code.google.com/p/chromium/issues/detail?id=3953 + // for more information. + if (filename == kWanWangProtocolHandlerPlugin) + return false; + + // We only work with newer versions of the Java plugin which use NPAPI only + // and don't depend on XPCOM. + if (filename == kJavaPlugin1 || filename == kJavaPlugin2) { + std::vector ver; + base::SplitString(info.version, '.', &ver); + int major, minor, update; + if (ver.size() == 4 && + base::StringToInt(ver[0], &major) && + base::StringToInt(ver[1], &minor) && + base::StringToInt(ver[2], &update)) { + if (major == 6 && minor == 0 && update < 120) + return false; // Java SE6 Update 11 or older. + } + } + + // Special WMP handling + + // If both the new and old WMP plugins exist, only load the new one. + if (filename == kNewWMPPlugin) { + if (dont_load_new_wmp_) + return false; + + for (size_t i = 0; i < plugins->size(); ++i) { + if ((*plugins)[i].path.BaseName().value() == kOldWMPPlugin) { + plugins->erase(plugins->begin() + i); + break; + } + } + } else if (filename == kOldWMPPlugin) { + for (size_t i = 0; i < plugins->size(); ++i) { + if ((*plugins)[i].path.BaseName().value() == kNewWMPPlugin) + return false; + } + } + + return true; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_stream.cc b/webkit/glue/plugins/plugin_stream.cc new file mode 100644 index 0000000..e465e2d --- /dev/null +++ b/webkit/glue/plugins/plugin_stream.cc @@ -0,0 +1,258 @@ +// Copyright (c) 2006-2008 The Chromium 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 : Support NP_ASFILEONLY mode +// TODO : Support NP_SEEK mode +// TODO : Support SEEKABLE=true in NewStream + +#include "webkit/glue/plugins/plugin_stream.h" + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "net/base/mime_util.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "googleurl/src/gurl.h" + +namespace NPAPI { + +PluginStream::~PluginStream() { + // always close our temporary files. + CloseTempFile(); + free(const_cast(stream_.url)); +} + +bool PluginStream::Open(const std::string &mime_type, + const std::string &headers, + uint32 length, + uint32 last_modified, + bool request_is_seekable) { + headers_ = headers; + NPP id = instance_->npp(); + stream_.end = length; + stream_.lastmodified = last_modified; + stream_.pdata = 0; + stream_.ndata = id->ndata; + stream_.notifyData = notify_data_; + if (!headers_.empty()) + stream_.headers = headers_.c_str(); + + bool seekable_stream = false; + if (request_is_seekable) { + std::string headers_lc = StringToLowerASCII(headers); + if (headers_lc.find("accept-ranges: bytes") != std::string::npos) { + seekable_stream = true; + } + } + + const char *char_mime_type = "application/x-unknown-content-type"; + std::string temp_mime_type; + if (!mime_type.empty()) { + char_mime_type = mime_type.c_str(); + } else { + GURL gurl(stream_.url); + +#if defined(OS_WIN) + FilePath path(UTF8ToWide(gurl.path())); +#elif defined(OS_POSIX) + FilePath path(gurl.path()); +#endif + if (net::GetMimeTypeFromFile(path, &temp_mime_type)) + char_mime_type = temp_mime_type.c_str(); + } + + // Silverlight expects a valid mime type + DCHECK(strlen(char_mime_type) != 0); + NPError err = instance_->NPP_NewStream((NPMIMEType)char_mime_type, + &stream_, seekable_stream, + &requested_plugin_mode_); + if (err != NPERR_NO_ERROR) { + Notify(err); + return false; + } + + opened_ = true; + + if (requested_plugin_mode_ == NP_SEEK) { + seekable_stream_ = true; + } + // If the plugin has requested certain modes, then we need a copy + // of this file on disk. Open it and save it as we go. + if (requested_plugin_mode_ == NP_ASFILEONLY || + requested_plugin_mode_ == NP_ASFILE) { + if (OpenTempFile() == false) + return false; + } + + mime_type_ = char_mime_type; + return true; +} + +int PluginStream::Write(const char *buffer, const int length, + int data_offset) { + // There may be two streams to write to - the plugin and the file. + // It is unclear what to do if we cannot write to both. The rules of + // this function are that the plugin must consume at least as many + // bytes as returned by the WriteReady call. So, we will attempt to + // write that many to both streams. If we can't write that many bytes + // to each stream, we'll return failure. + + DCHECK(opened_); + if (WriteToFile(buffer, length) && + WriteToPlugin(buffer, length, data_offset)) + return length; + + return -1; +} + +bool PluginStream::WriteToFile(const char *buf, size_t length) { + // For ASFILEONLY, ASFILE, and SEEK modes, we need to write + // to the disk + if (TempFileIsValid() && + (requested_plugin_mode_ == NP_ASFILE || + requested_plugin_mode_ == NP_ASFILEONLY) ) { + size_t totalBytesWritten = 0, bytes; + do { + bytes = WriteBytes(buf, length); + totalBytesWritten += bytes; + } while (bytes > 0U && totalBytesWritten < length); + + if (totalBytesWritten != length) + return false; + } + + return true; +} + +bool PluginStream::WriteToPlugin(const char *buf, const int length, + const int data_offset) { + // For NORMAL and ASFILE modes, we send the data to the plugin now + if (requested_plugin_mode_ != NP_NORMAL && + requested_plugin_mode_ != NP_ASFILE && + requested_plugin_mode_ != NP_SEEK) + return true; + + int written = TryWriteToPlugin(buf, length, data_offset); + if (written == -1) + return false; + + if (written < length) { + // Buffer the remaining data. + size_t remaining = length - written; + size_t previous_size = delivery_data_.size(); + delivery_data_.resize(previous_size + remaining); + data_offset_ = data_offset; + memcpy(&delivery_data_[previous_size], buf + written, remaining); + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &PluginStream::OnDelayDelivery)); + } + + return true; +} + +void PluginStream::OnDelayDelivery() { + // It is possible that the plugin stream may have closed before the task + // was hit. + if (!opened_) { + return; + } + + int size = static_cast(delivery_data_.size()); + int written = TryWriteToPlugin(&delivery_data_.front(), size, + data_offset_); + if (written > 0) { + // Remove the data that we already wrote. + delivery_data_.erase(delivery_data_.begin(), + delivery_data_.begin() + written); + } +} + +int PluginStream::TryWriteToPlugin(const char *buf, const int length, + const int data_offset) { + int byte_offset = 0; + + if (data_offset > 0) + data_offset_ = data_offset; + + while (byte_offset < length) { + int bytes_remaining = length - byte_offset; + int bytes_to_write = instance_->NPP_WriteReady(&stream_); + if (bytes_to_write > bytes_remaining) + bytes_to_write = bytes_remaining; + + if (bytes_to_write == 0) + return byte_offset; + + int bytes_consumed = instance_->NPP_Write( + &stream_, data_offset_, bytes_to_write, + const_cast(buf + byte_offset)); + if (bytes_consumed < 0) { + // The plugin failed, which means that we need to close the stream. + Close(NPRES_NETWORK_ERR); + return -1; + } + if (bytes_consumed == 0) { + // The plugin couldn't take all of the data now. + return byte_offset; + } + + // The plugin might report more that we gave it. + bytes_consumed = std::min(bytes_consumed, bytes_to_write); + + data_offset_ += bytes_consumed; + byte_offset += bytes_consumed; + } + + if (close_on_write_data_) + Close(NPRES_DONE); + + return length; +} + +bool PluginStream::Close(NPReason reason) { + if (opened_ == true) { + opened_ = false; + + if (delivery_data_.size()) { + if (reason == NPRES_DONE) { + // There is more data to be streamed, don't destroy the stream now. + close_on_write_data_ = true; + return true; + } else { + // Stop any pending data from being streamed + delivery_data_.resize(0); + } + } + + // If we have a temp file, be sure to close it. + // Also, allow the plugin to access it now. + if (TempFileIsValid()) { + CloseTempFile(); + if (reason == NPRES_DONE) + WriteAsFile(); + } + + if (stream_.ndata != NULL) { + // Stream hasn't been closed yet. + NPError err = instance_->NPP_DestroyStream(&stream_, reason); + DCHECK(err == NPERR_NO_ERROR); + } + } + + Notify(reason); + return true; +} + +webkit_glue::WebPluginResourceClient* PluginStream::AsResourceClient() { + return NULL; +} + +void PluginStream::Notify(NPReason reason) { + if (notify_needed_) { + instance_->NPP_URLNotify(stream_.url, reason, notify_data_); + notify_needed_ = false; + } +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_stream.h b/webkit/glue/plugins/plugin_stream.h new file mode 100644 index 0000000..c5975b4 --- /dev/null +++ b/webkit/glue/plugins/plugin_stream.h @@ -0,0 +1,156 @@ +// 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 WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ +#define WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ + +#include "build/build_config.h" + +#include +#include + +#if defined(OS_POSIX) +#include "base/file_path.h" +#endif +#include "base/ref_counted.h" +#include "third_party/npapi/bindings/npapi.h" + +namespace webkit_glue { +class WebPluginResourceClient; +} + +namespace NPAPI { + +class PluginInstance; + +// Base class for a NPAPI stream. Tracks basic elements +// of a stream for NPAPI notifications and stream position. +class PluginStream : public base::RefCounted { + public: + // Create a new PluginStream object. If needNotify is true, then the + // plugin will be notified when the stream has been fully sent. + PluginStream(PluginInstance *instance, + const char *url, + bool need_notify, + void *notify_data); + + // In case of a redirect, this can be called to update the url. But it must + // be called before Open(). + void UpdateUrl(const char* url); + + // Opens the stream to the Plugin. + // If the mime-type is not specified, we'll try to find one based on the + // mime-types table and the extension (if any) in the URL. + // If the size of the stream is known, use length to set the size. If + // not known, set length to 0. + // The request_is_seekable parameter indicates whether byte range requests + // can be issued on the stream. + bool Open(const std::string &mime_type, + const std::string &headers, + uint32 length, + uint32 last_modified, + bool request_is_seekable); + + // Writes to the stream. + int Write(const char *buf, const int len, int data_offset); + + // Write the result as a file. + void WriteAsFile(); + + // Notify the plugin that a stream is complete. + void Notify(NPReason reason); + + // Close the stream. + virtual bool Close(NPReason reason); + + virtual webkit_glue::WebPluginResourceClient* AsResourceClient(); + + // Cancels any HTTP requests initiated by the stream. + virtual void CancelRequest() {} + + const NPStream* stream() const { return &stream_; } + + // setter/getter for the seekable attribute on the stream. + bool seekable() const { return seekable_stream_; } + + void set_seekable(bool seekable) { seekable_stream_ = seekable; } + + // getters for reading the notification related attributes on the stream. + bool notify_needed() const { return notify_needed_; } + + void* notify_data() const { return notify_data_; } + + std::string pending_redirect_url() const { return pending_redirect_url_; } + + protected: + friend class base::RefCounted; + + virtual ~PluginStream(); + + PluginInstance* instance() { return instance_.get(); } + // Check if the stream is open. + bool open() { return opened_; } + + // If the plugin participates in HTTP URL redirect handling then this member + // holds the url being redirected to while we wait for the plugin to make a + // decision on whether to allow or deny the redirect. + std::string pending_redirect_url_; + + private: + + // Open a temporary file for this stream. + // If successful, will set temp_file_name_, temp_file_handle_, and + // return true. + bool OpenTempFile(); + + // Closes the temporary file if it is open. + void CloseTempFile(); + + // Sends the data to the file. Called From WriteToFile. + size_t WriteBytes(const char *buf, size_t length); + + // Sends the data to the file if it's open. + bool WriteToFile(const char *buf, size_t length); + + // Sends the data to the plugin. If it's not ready, handles buffering it + // and retrying later. + bool WriteToPlugin(const char *buf, const int length, const int data_offset); + + // Send the data to the plugin, returning how many bytes it accepted, or -1 + // if an error occurred. + int TryWriteToPlugin(const char *buf, const int length, + const int data_offset); + + // The callback which calls TryWriteToPlugin. + void OnDelayDelivery(); + + // Returns true if the temp file is valid and open for writing. + bool TempFileIsValid(); + + private: + NPStream stream_; + std::string headers_; + scoped_refptr instance_; + bool notify_needed_; + void * notify_data_; + bool close_on_write_data_; + uint16 requested_plugin_mode_; + bool opened_; +#if defined(OS_WIN) + char temp_file_name_[MAX_PATH]; + HANDLE temp_file_handle_; +#elif defined(OS_POSIX) + FILE* temp_file_; + FilePath temp_file_path_; +#endif + std::vector delivery_data_; + int data_offset_; + bool seekable_stream_; + std::string mime_type_; + DISALLOW_COPY_AND_ASSIGN(PluginStream); +}; + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGINS_PLUGIN_STREAM_H_ diff --git a/webkit/glue/plugins/plugin_stream_posix.cc b/webkit/glue/plugins/plugin_stream_posix.cc new file mode 100644 index 0000000..d0e2291 --- /dev/null +++ b/webkit/glue/plugins/plugin_stream_posix.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/plugin_stream.h" + +#include + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_instance.h" + +namespace NPAPI { + +PluginStream::PluginStream( + PluginInstance *instance, + const char *url, + bool need_notify, + void *notify_data) + : instance_(instance), + notify_needed_(need_notify), + notify_data_(notify_data), + close_on_write_data_(false), + requested_plugin_mode_(NP_NORMAL), + opened_(false), + temp_file_(NULL), + temp_file_path_(), + data_offset_(0), + seekable_stream_(false) { + memset(&stream_, 0, sizeof(stream_)); + stream_.url = strdup(url); +} + +void PluginStream::UpdateUrl(const char* url) { + DCHECK(!opened_); + free(const_cast(stream_.url)); + stream_.url = strdup(url); +} + +void PluginStream::WriteAsFile() { + if (requested_plugin_mode_ == NP_ASFILE || + requested_plugin_mode_ == NP_ASFILEONLY) + instance_->NPP_StreamAsFile(&stream_, temp_file_path_.value().c_str()); +} + +size_t PluginStream::WriteBytes(const char *buf, size_t length) { + return fwrite(buf, sizeof(char), length, temp_file_); +} + +bool PluginStream::OpenTempFile() { + DCHECK(temp_file_ == NULL); + + if (file_util::CreateTemporaryFile(&temp_file_path_)) + temp_file_ = file_util::OpenFile(temp_file_path_, "a"); + + if (!temp_file_) { + temp_file_path_ = FilePath(""); + return false; + } + + return true; +} + +void PluginStream::CloseTempFile() { + file_util::CloseFile(temp_file_); + temp_file_ = NULL; +} + +bool PluginStream::TempFileIsValid() { + return temp_file_ != NULL; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_stream_url.cc b/webkit/glue/plugins/plugin_stream_url.cc new file mode 100644 index 0000000..7f9f355 --- /dev/null +++ b/webkit/glue/plugins/plugin_stream_url.cc @@ -0,0 +1,130 @@ +// 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 "webkit/glue/plugins/plugin_stream_url.h" + +#include "net/http/http_response_headers.h" +#include "webkit/glue/plugins/plugin_host.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/webplugin.h" + +namespace NPAPI { + +PluginStreamUrl::PluginStreamUrl( + unsigned long resource_id, + const GURL &url, + PluginInstance *instance, + bool notify_needed, + void *notify_data) + : PluginStream(instance, url.spec().c_str(), notify_needed, notify_data), + url_(url), + id_(resource_id) { +} + +PluginStreamUrl::~PluginStreamUrl() { + if (instance() && instance()->webplugin()) { + instance()->webplugin()->ResourceClientDeleted(AsResourceClient()); + } +} + +bool PluginStreamUrl::Close(NPReason reason) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the destroy stream handler. + scoped_refptr protect(this); + CancelRequest(); + bool result = PluginStream::Close(reason); + instance()->RemoveStream(this); + return result; +} + +webkit_glue::WebPluginResourceClient* PluginStreamUrl::AsResourceClient() { + return static_cast(this); +} + +void PluginStreamUrl::WillSendRequest(const GURL& url, int http_status_code) { + if (notify_needed()) { + // If the plugin participates in HTTP url redirect handling then notify it. + if (net::HttpResponseHeaders::IsRedirectResponseCode(http_status_code) && + instance()->handles_url_redirects()) { + pending_redirect_url_ = url.spec(); + instance()->NPP_URLRedirectNotify(url.spec().c_str(), http_status_code, + notify_data()); + return; + } + } + url_ = url; + UpdateUrl(url.spec().c_str()); +} + +void PluginStreamUrl::DidReceiveResponse(const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified, + bool request_is_seekable) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the new stream handler. + scoped_refptr protect(this); + + bool opened = Open(mime_type, + headers, + expected_length, + last_modified, + request_is_seekable); + if (!opened) { + CancelRequest(); + instance()->RemoveStream(this); + } else { + if (id_ > 0) + instance()->webplugin()->SetDeferResourceLoading(id_, false); + } +} + +void PluginStreamUrl::DidReceiveData(const char* buffer, int length, + int data_offset) { + if (!open()) + return; + + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the write handlers + scoped_refptr protect(this); + + if (length > 0) { + // The PluginStreamUrl instance could get deleted if the plugin fails to + // accept data in NPP_Write. + if (Write(const_cast(buffer), length, data_offset) > 0) { + if (id_ > 0) + instance()->webplugin()->SetDeferResourceLoading(id_, false); + } + } +} + +void PluginStreamUrl::DidFinishLoading() { + if (!seekable()) { + Close(NPRES_DONE); + } +} + +void PluginStreamUrl::DidFail() { + Close(NPRES_NETWORK_ERR); +} + +bool PluginStreamUrl::IsMultiByteResponseExpected() { + return seekable(); +} + +int PluginStreamUrl::ResourceId() { + return id_; +} + +void PluginStreamUrl::CancelRequest() { + if (id_ > 0) { + if (instance()->webplugin()) { + instance()->webplugin()->CancelResource(id_); + } + id_ = 0; + } +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_stream_url.h b/webkit/glue/plugins/plugin_stream_url.h new file mode 100644 index 0000000..8642897 --- /dev/null +++ b/webkit/glue/plugins/plugin_stream_url.h @@ -0,0 +1,65 @@ +// 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 WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_URL_H__ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_URL_H__ + + +#include "webkit/glue/plugins/plugin_stream.h" +#include "webkit/glue/plugins/webplugin.h" +#include "googleurl/src/gurl.h" + +namespace NPAPI { + +class PluginInstance; + +// A NPAPI Stream based on a URL. +class PluginStreamUrl : public PluginStream, + public webkit_glue::WebPluginResourceClient { + public: + // Create a new stream for sending to the plugin by fetching + // a URL. If notifyNeeded is set, then the plugin will be notified + // when the stream has been fully sent to the plugin. Initialize + // must be called before the object is used. + PluginStreamUrl(unsigned long resource_id, + const GURL &url, + PluginInstance *instance, + bool notify_needed, + void *notify_data); + virtual ~PluginStreamUrl(); + + // 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); + + virtual webkit_glue::WebPluginResourceClient* AsResourceClient(); + + virtual void CancelRequest(); + + // + // WebPluginResourceClient methods + // + virtual void WillSendRequest(const GURL& url, int 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); + virtual void DidReceiveData(const char* buffer, int length, int data_offset); + virtual void DidFinishLoading(); + virtual void DidFail(); + virtual bool IsMultiByteResponseExpected(); + virtual int ResourceId(); + + private: + GURL url_; + unsigned long id_; + + DISALLOW_COPY_AND_ASSIGN(PluginStreamUrl); +}; + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_STREAM_URL_H__ diff --git a/webkit/glue/plugins/plugin_stream_win.cc b/webkit/glue/plugins/plugin_stream_win.cc new file mode 100644 index 0000000..0b6fcbd --- /dev/null +++ b/webkit/glue/plugins/plugin_stream_win.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/plugin_stream.h" + +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_instance.h" + +namespace NPAPI { + +PluginStream::PluginStream( + PluginInstance *instance, + const char *url, + bool need_notify, + void *notify_data) + : instance_(instance), + notify_needed_(need_notify), + notify_data_(notify_data), + close_on_write_data_(false), + opened_(false), + requested_plugin_mode_(NP_NORMAL), + temp_file_handle_(INVALID_HANDLE_VALUE), + seekable_stream_(false), + data_offset_(0) { + memset(&stream_, 0, sizeof(stream_)); + stream_.url = _strdup(url); + temp_file_name_[0] = '\0'; +} + +void PluginStream::UpdateUrl(const char* url) { + DCHECK(!opened_); + free(const_cast(stream_.url)); + stream_.url = _strdup(url); + pending_redirect_url_.clear(); +} + +void PluginStream::WriteAsFile() { + if (requested_plugin_mode_ == NP_ASFILE || + requested_plugin_mode_ == NP_ASFILEONLY) + instance_->NPP_StreamAsFile(&stream_, temp_file_name_); +} + +size_t PluginStream::WriteBytes(const char *buf, size_t length) { + DWORD bytes; + + if (!WriteFile(temp_file_handle_, buf, length, &bytes, 0)) + return 0U; + + return static_cast(bytes); +} + +bool PluginStream::OpenTempFile() { + DCHECK(temp_file_handle_ == INVALID_HANDLE_VALUE); + + // The reason for using all the Ascii versions of these filesystem + // calls is that the filename which we pass back to the plugin + // via NPAPI is an ascii filename. Otherwise, we'd use wide-chars. + // + // TODO: + // This is a bug in NPAPI itself, and it needs to be fixed. + // The case which will fail is if a user has a multibyte name, + // but has the system locale set to english. GetTempPathA will + // return junk in this case, causing us to be unable to open the + // file. + + char temp_directory[MAX_PATH]; + if (GetTempPathA(MAX_PATH, temp_directory) == 0) + return false; + if (GetTempFileNameA(temp_directory, "npstream", 0, temp_file_name_) == 0) + return false; + temp_file_handle_ = CreateFileA(temp_file_name_, + FILE_ALL_ACCESS, + FILE_SHARE_READ, + 0, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0); + if (temp_file_handle_ == INVALID_HANDLE_VALUE) { + temp_file_name_[0] = '\0'; + return false; + } + return true; +} + +void PluginStream::CloseTempFile() { + if (temp_file_handle_ != INVALID_HANDLE_VALUE) { + CloseHandle(temp_file_handle_); + temp_file_handle_ = INVALID_HANDLE_VALUE; + } +} + +bool PluginStream::TempFileIsValid() { + return temp_file_handle_ != INVALID_HANDLE_VALUE; +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_string_stream.cc b/webkit/glue/plugins/plugin_string_stream.cc new file mode 100644 index 0000000..f174267 --- /dev/null +++ b/webkit/glue/plugins/plugin_string_stream.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/plugin_string_stream.h" + +#include "googleurl/src/gurl.h" + +namespace NPAPI { + +PluginStringStream::PluginStringStream( + PluginInstance* instance, + const GURL& url, + bool notify_needed, + void* notify_data) + : PluginStream(instance, url.spec().c_str(), notify_needed, notify_data) { +} + +PluginStringStream::~PluginStringStream() { +} + +void PluginStringStream::SendToPlugin(const std::string &data, + const std::string &mime_type) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the plugin stream callbacks. + scoped_refptr protect(this); + + int length = static_cast(data.length()); + if (Open(mime_type, std::string(), length, 0, false)) { + // TODO - check if it was not fully sent, and figure out a backup plan. + int written = Write(data.c_str(), length, 0); + NPReason reason = written == length ? NPRES_DONE : NPRES_NETWORK_ERR; + Close(reason); + } +} + +} diff --git a/webkit/glue/plugins/plugin_string_stream.h b/webkit/glue/plugins/plugin_string_stream.h new file mode 100644 index 0000000..68db2bf --- /dev/null +++ b/webkit/glue/plugins/plugin_string_stream.h @@ -0,0 +1,39 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGIN_PLUGIN_STRING_STREAM_H_ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_STRING_STREAM_H_ + +#include "webkit/glue/plugins/plugin_stream.h" + +class GURL; + +namespace NPAPI { + +class PluginInstance; + +// An NPAPI stream from a string. +class PluginStringStream : public PluginStream { + public: + // Create a new stream for sending to the plugin. + // If notify_needed, will notify the plugin after the data has + // all been sent. + PluginStringStream(PluginInstance* instance, + const GURL& url, + bool notify_needed, + void* notify_data); + + // Initiates the sending of data to the plugin. + void SendToPlugin(const std::string& data, + const std::string& mime_type); + + private: + virtual ~PluginStringStream(); + + DISALLOW_COPY_AND_ASSIGN(PluginStringStream); +}; + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_STRING_STREAM_H_ diff --git a/webkit/glue/plugins/plugin_stubs.cc b/webkit/glue/plugins/plugin_stubs.cc new file mode 100644 index 0000000..f8210c30 --- /dev/null +++ b/webkit/glue/plugins/plugin_stubs.cc @@ -0,0 +1,30 @@ +// Copyright (c) 2006-2008 The Chromium 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 stubs out some functions needed to make the linker happy +// without linking in all the plugin code. It should be removed once +// we have plugins working on all platforms. + +// TODO(port): remove this file. + +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_stream.h" + +namespace NPAPI { + +PluginStream::~PluginStream() { + NOTIMPLEMENTED(); +} + +bool PluginStream::Close(NPReason reason) { + NOTIMPLEMENTED(); + return false; +} + +void PluginInstance::NPP_StreamAsFile(NPStream*, const char*) { + NOTIMPLEMENTED(); +} + +} // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.h b/webkit/glue/plugins/plugin_web_event_converter_mac.h new file mode 100644 index 0000000..ec5b86f --- /dev/null +++ b/webkit/glue/plugins/plugin_web_event_converter_mac.h @@ -0,0 +1,60 @@ +// 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 WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ + +#include "third_party/npapi/bindings/npapi.h" + +namespace WebKit { +class WebInputEvent; +class WebKeyboardEvent; +class WebMouseEvent; +class WebMouseWheelEvent; +} + +// Utility class to translating WebInputEvent structs to equivalent structures +// suitable for sending to Mac plugins (via NPP_HandleEvent). +class PluginWebEventConverter { + public: + PluginWebEventConverter() {} + virtual ~PluginWebEventConverter() {} + + // Initializes a converter for the given web event. Returns false if the event + // could not be converted. + virtual bool InitWithEvent(const WebKit::WebInputEvent& web_event); + + // Returns a pointer to a plugin event--suitable for passing to + // NPP_HandleEvent--corresponding to the the web event this converter was + // created with. The pointer is valid only as long as this object is. + // Returns NULL iff InitWithEvent returned false. + virtual void* plugin_event() = 0; + +protected: + // To be overridden by subclasses to store a converted plugin representation + // of the given web event, suitable for returning from plugin_event. + // Returns true if the event was successfully converted. + virtual bool ConvertKeyboardEvent( + const WebKit::WebKeyboardEvent& web_event) = 0; + virtual bool ConvertMouseEvent(const WebKit::WebMouseEvent& web_event) = 0; + virtual bool ConvertMouseWheelEvent( + const WebKit::WebMouseWheelEvent& web_event) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(PluginWebEventConverter); +}; + +// Factory for generating PluginWebEventConverter objects by event model. +class PluginWebEventConverterFactory { + public: + // Returns a new PluginWebEventConverter corresponding to the given plugin + // event model. + static PluginWebEventConverter* + CreateConverterForModel(NPEventModel event_model); + + private: + DISALLOW_COPY_AND_ASSIGN(PluginWebEventConverterFactory); +}; + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.mm b/webkit/glue/plugins/plugin_web_event_converter_mac.mm new file mode 100644 index 0000000..12d5cc6 --- /dev/null +++ b/webkit/glue/plugins/plugin_web_event_converter_mac.mm @@ -0,0 +1,359 @@ +// 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. + +#import + +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_web_event_converter_mac.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" + +using WebKit::WebInputEvent; +using WebKit::WebKeyboardEvent; +using WebKit::WebMouseEvent; +using WebKit::WebMouseWheelEvent; + +namespace { + +// Returns true if the caps lock flag should be set for the given event. +bool CapsLockIsActive(const WebInputEvent& event) { + // Only key events have accurate information for the caps lock flag; see + // . + // For other types, use the live state. + if (WebInputEvent::isKeyboardEventType(event.type)) + return (event.modifiers & WebInputEvent::CapsLockOn) != 0; + else + return ([[NSApp currentEvent] modifierFlags] & NSAlphaShiftKeyMask) != 0; +} + +} // namespace + +#pragma mark - + +#ifndef NP_NO_CARBON + +// Converter implementation for the Carbon event model. +class CarbonPluginWebEventConverter : public PluginWebEventConverter { + public: + CarbonPluginWebEventConverter() {} + virtual ~CarbonPluginWebEventConverter() {} + + virtual bool InitWithEvent(const WebInputEvent& web_event); + + virtual void* plugin_event() { return &carbon_event_; } + + protected: + virtual bool ConvertKeyboardEvent(const WebKeyboardEvent& key_event); + virtual bool ConvertMouseEvent(const WebMouseEvent& mouse_event); + virtual bool ConvertMouseWheelEvent(const WebMouseWheelEvent& wheel_event); + + private: + // Returns the Carbon translation of web_event's modifiers. + static EventModifiers CarbonModifiers(const WebInputEvent& web_event); + + NPEvent carbon_event_; + + DISALLOW_COPY_AND_ASSIGN(CarbonPluginWebEventConverter); +}; + +bool CarbonPluginWebEventConverter::InitWithEvent( + const WebInputEvent& web_event) { + memset(&carbon_event_, 0, sizeof(carbon_event_)); + // Set the fields common to all event types. + carbon_event_.when = TickCount(); + carbon_event_.modifiers |= CarbonModifiers(web_event); + + return PluginWebEventConverter::InitWithEvent(web_event); +} + +bool CarbonPluginWebEventConverter::ConvertKeyboardEvent( + const WebKeyboardEvent& key_event) { + // TODO: Figure out how to handle Unicode input to plugins, if that's + // even possible in the NPAPI Carbon event model. + carbon_event_.message = (key_event.nativeKeyCode << 8) & keyCodeMask; + carbon_event_.message |= key_event.text[0] & charCodeMask; + carbon_event_.modifiers |= btnState; + + switch (key_event.type) { + case WebInputEvent::KeyDown: + if (key_event.modifiers & WebInputEvent::IsAutoRepeat) + carbon_event_.what = autoKey; + else + carbon_event_.what = keyDown; + return true; + case WebInputEvent::KeyUp: + carbon_event_.what = keyUp; + return true; + case WebInputEvent::RawKeyDown: + case WebInputEvent::Char: + // May be used eventually for IME, but currently not needed. + return false; + default: + NOTREACHED(); + return false; + } +} + +bool CarbonPluginWebEventConverter::ConvertMouseEvent( + const WebMouseEvent& mouse_event) { + carbon_event_.where.h = mouse_event.globalX; + carbon_event_.where.v = mouse_event.globalY; + + // Default to "button up"; override this for mouse down events below. + carbon_event_.modifiers |= btnState; + + switch (mouse_event.button) { + case WebMouseEvent::ButtonLeft: + break; + case WebMouseEvent::ButtonMiddle: + carbon_event_.modifiers |= cmdKey; + break; + case WebMouseEvent::ButtonRight: + carbon_event_.modifiers |= controlKey; + break; + default: + NOTIMPLEMENTED(); + } + switch (mouse_event.type) { + case WebInputEvent::MouseMove: + carbon_event_.what = nullEvent; + return true; + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: + carbon_event_.what = NPEventType_AdjustCursorEvent; + return true; + case WebInputEvent::MouseDown: + carbon_event_.modifiers &= ~btnState; + carbon_event_.what = mouseDown; + return true; + case WebInputEvent::MouseUp: + carbon_event_.what = mouseUp; + return true; + default: + NOTREACHED(); + return false; + } +} + +bool CarbonPluginWebEventConverter::ConvertMouseWheelEvent( + const WebMouseWheelEvent& wheel_event) { + return false; // The Carbon NPAPI event model has no "mouse wheel" concept. +} + +EventModifiers CarbonPluginWebEventConverter::CarbonModifiers( + const WebInputEvent& web_event) { + NSInteger modifiers = 0; + if (web_event.modifiers & WebInputEvent::ControlKey) + modifiers |= controlKey; + if (web_event.modifiers & WebInputEvent::ShiftKey) + modifiers |= shiftKey; + if (web_event.modifiers & WebInputEvent::AltKey) + modifiers |= optionKey; + if (web_event.modifiers & WebInputEvent::MetaKey) + modifiers |= cmdKey; + if (CapsLockIsActive(web_event)) + modifiers |= alphaLock; + return modifiers; +} + +#endif // !NP_NO_CARBON + +#pragma mark - + +// Converter implementation for the Cocoa event model. +class CocoaPluginWebEventConverter : public PluginWebEventConverter { +public: + CocoaPluginWebEventConverter() {} + virtual ~CocoaPluginWebEventConverter() {} + + virtual bool InitWithEvent(const WebInputEvent& web_event); + + virtual void* plugin_event() { return &cocoa_event_; } + +protected: + virtual bool ConvertKeyboardEvent(const WebKeyboardEvent& key_event); + virtual bool ConvertMouseEvent(const WebMouseEvent& mouse_event); + virtual bool ConvertMouseWheelEvent(const WebMouseWheelEvent& wheel_event); + +private: + // Returns the Cocoa translation of web_event's modifiers. + static NSUInteger CocoaModifiers(const WebInputEvent& web_event); + + // Returns true if the given key is a modifier key. + static bool KeyIsModifier(int native_key_code); + + NPCocoaEvent cocoa_event_; + + DISALLOW_COPY_AND_ASSIGN(CocoaPluginWebEventConverter); +}; + +bool CocoaPluginWebEventConverter::InitWithEvent( + const WebInputEvent& web_event) { + memset(&cocoa_event_, 0, sizeof(cocoa_event_)); + return PluginWebEventConverter::InitWithEvent(web_event); +} + +bool CocoaPluginWebEventConverter::ConvertKeyboardEvent( + const WebKeyboardEvent& key_event) { + cocoa_event_.data.key.keyCode = key_event.nativeKeyCode; + + cocoa_event_.data.key.modifierFlags |= CocoaModifiers(key_event); + + // Modifier keys have their own event type, and don't get character or + // repeat data. + if (KeyIsModifier(key_event.nativeKeyCode)) { + cocoa_event_.type = NPCocoaEventFlagsChanged; + return true; + } + + cocoa_event_.data.key.characters = reinterpret_cast( + [NSString stringWithFormat:@"%S", key_event.text]); + cocoa_event_.data.key.charactersIgnoringModifiers = + reinterpret_cast( + [NSString stringWithFormat:@"%S", key_event.unmodifiedText]); + + if (key_event.modifiers & WebInputEvent::IsAutoRepeat) + cocoa_event_.data.key.isARepeat = true; + + switch (key_event.type) { + case WebInputEvent::KeyDown: + cocoa_event_.type = NPCocoaEventKeyDown; + return true; + case WebInputEvent::KeyUp: + cocoa_event_.type = NPCocoaEventKeyUp; + return true; + case WebInputEvent::RawKeyDown: + case WebInputEvent::Char: + // May be used eventually for IME, but currently not needed. + return false; + default: + NOTREACHED(); + return false; + } +} + +bool CocoaPluginWebEventConverter::ConvertMouseEvent( + const WebMouseEvent& mouse_event) { + cocoa_event_.data.mouse.pluginX = mouse_event.x; + cocoa_event_.data.mouse.pluginY = mouse_event.y; + cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(mouse_event); + cocoa_event_.data.mouse.clickCount = mouse_event.clickCount; + switch (mouse_event.button) { + case WebMouseEvent::ButtonLeft: + cocoa_event_.data.mouse.buttonNumber = 0; + break; + case WebMouseEvent::ButtonMiddle: + cocoa_event_.data.mouse.buttonNumber = 2; + break; + case WebMouseEvent::ButtonRight: + cocoa_event_.data.mouse.buttonNumber = 1; + break; + default: + cocoa_event_.data.mouse.buttonNumber = mouse_event.button; + break; + } + switch (mouse_event.type) { + case WebInputEvent::MouseDown: + cocoa_event_.type = NPCocoaEventMouseDown; + return true; + case WebInputEvent::MouseUp: + cocoa_event_.type = NPCocoaEventMouseUp; + return true; + case WebInputEvent::MouseMove: { + bool mouse_is_down = + (mouse_event.modifiers & WebInputEvent::LeftButtonDown) || + (mouse_event.modifiers & WebInputEvent::RightButtonDown) || + (mouse_event.modifiers & WebInputEvent::MiddleButtonDown); + cocoa_event_.type = mouse_is_down ? NPCocoaEventMouseDragged + : NPCocoaEventMouseMoved; + return true; + } + case WebInputEvent::MouseEnter: + cocoa_event_.type = NPCocoaEventMouseEntered; + return true; + case WebInputEvent::MouseLeave: + cocoa_event_.type = NPCocoaEventMouseExited; + return true; + default: + NOTREACHED(); + return false; + } +} + +bool CocoaPluginWebEventConverter::ConvertMouseWheelEvent( + const WebMouseWheelEvent& wheel_event) { + cocoa_event_.type = NPCocoaEventScrollWheel; + cocoa_event_.data.mouse.pluginX = wheel_event.x; + cocoa_event_.data.mouse.pluginY = wheel_event.y; + cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(wheel_event); + cocoa_event_.data.mouse.deltaX = wheel_event.deltaX; + cocoa_event_.data.mouse.deltaY = wheel_event.deltaY; + return true; +} + +NSUInteger CocoaPluginWebEventConverter::CocoaModifiers( + const WebInputEvent& web_event) { + NSInteger modifiers = 0; + if (web_event.modifiers & WebInputEvent::ControlKey) + modifiers |= NSControlKeyMask; + if (web_event.modifiers & WebInputEvent::ShiftKey) + modifiers |= NSShiftKeyMask; + if (web_event.modifiers & WebInputEvent::AltKey) + modifiers |= NSAlternateKeyMask; + if (web_event.modifiers & WebInputEvent::MetaKey) + modifiers |= NSCommandKeyMask; + if (CapsLockIsActive(web_event)) + modifiers |= NSAlphaShiftKeyMask; + return modifiers; +} + +bool CocoaPluginWebEventConverter::KeyIsModifier(int native_key_code) { + switch (native_key_code) { + case 55: // Left command + case 54: // Right command + case 58: // Left option + case 61: // Right option + case 59: // Left control + case 62: // Right control + case 56: // Left shift + case 60: // Right shift + case 57: // Caps lock + return true; + default: + return false; + } +} + +#pragma mark - + +bool PluginWebEventConverter::InitWithEvent(const WebInputEvent& web_event) { + if (web_event.type == WebInputEvent::MouseWheel) { + return ConvertMouseWheelEvent( + *static_cast(&web_event)); + } else if (WebInputEvent::isMouseEventType(web_event.type)) { + return ConvertMouseEvent(*static_cast(&web_event)); + } else if (WebInputEvent::isKeyboardEventType(web_event.type)) { + return ConvertKeyboardEvent( + *static_cast(&web_event)); + } + DLOG(WARNING) << "Unknown event type " << web_event.type; + return false; +} + +#pragma mark - + +PluginWebEventConverter* + PluginWebEventConverterFactory::CreateConverterForModel( + NPEventModel event_model) { + switch (event_model) { + case NPEventModelCocoa: + return new CocoaPluginWebEventConverter(); +#ifndef NP_NO_CARBON + case NPEventModelCarbon: + return new CarbonPluginWebEventConverter(); +#endif + default: + NOTIMPLEMENTED(); + return NULL; + } +} diff --git a/webkit/glue/plugins/quickdraw_drawing_manager_mac.cc b/webkit/glue/plugins/quickdraw_drawing_manager_mac.cc new file mode 100644 index 0000000..424cc1e --- /dev/null +++ b/webkit/glue/plugins/quickdraw_drawing_manager_mac.cc @@ -0,0 +1,154 @@ +// 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 NP_NO_QUICKDRAW + +#include "webkit/glue/plugins/quickdraw_drawing_manager_mac.h" + +#include "webkit/glue/plugins/coregraphics_private_symbols_mac.h" + +// Turn off GCC warnings about deprecated functions (since QuickDraw is a +// deprecated API). According to the GCC documentation, this can only be done +// per file, not pushed and popped like some options can be. +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +QuickDrawDrawingManager::QuickDrawDrawingManager() + : plugin_window_(NULL), target_context_(NULL), fast_path_enabled_(false), + current_port_(NULL), target_world_(NULL), plugin_world_(NULL) {} + +QuickDrawDrawingManager::~QuickDrawDrawingManager() { + DestroyGWorlds(); +} + +void QuickDrawDrawingManager::SetFastPathEnabled(bool enabled) { + if (fast_path_enabled_ == enabled) + return; + + fast_path_enabled_ = enabled; + if (enabled) { + if (!target_world_) + UpdateGWorlds(); + // Copy our last window snapshot into our new source, since the plugin + // may not repaint everything. + CopyGWorldBits(target_world_, plugin_world_, plugin_size_); + current_port_ = plugin_world_; + } else { + current_port_ = GetWindowPort(plugin_window_); + } +} + +void QuickDrawDrawingManager::SetTargetContext(CGContextRef context, + const gfx::Size& plugin_size) { + target_context_ = context; + if (plugin_size != plugin_size_) { + plugin_size_ = plugin_size; + // Pitch the old GWorlds, since they are the wrong size now. + DestroyGWorlds(); + if (fast_path_enabled_) + UpdateGWorlds(); + } +} + +void QuickDrawDrawingManager::SetPluginWindow(WindowRef window) { + plugin_window_ = window; + if (!fast_path_enabled_) + current_port_ = GetWindowPort(window); +} + +void QuickDrawDrawingManager::UpdateContext() { + if (fast_path_enabled_) + CopyGWorldBits(plugin_world_, target_world_, plugin_size_); + else + ScrapeWindow(plugin_window_, target_context_, plugin_size_); +} + +bool QuickDrawDrawingManager::IsFastPathEnabled() { + return fast_path_enabled_; +} + +void QuickDrawDrawingManager::MakePortCurrent() { + if (fast_path_enabled_) + SetGWorld(current_port_, NULL); + else + SetPort(current_port_); +} + +void QuickDrawDrawingManager::DestroyGWorlds() { + if (plugin_world_) { + DisposeGWorld(plugin_world_); + plugin_world_ = NULL; + } + if (target_world_) { + DisposeGWorld(target_world_); + target_world_ = NULL; + } +} + +void QuickDrawDrawingManager::UpdateGWorlds() { + DestroyGWorlds(); + if (!target_context_) + return; + + Rect window_bounds = { + 0, 0, plugin_size_.height(), plugin_size_.width() + }; + // Create a GWorld pointing at the same bits as our target context. + if (target_context_) { + NewGWorldFromPtr( + &target_world_, k32BGRAPixelFormat, &window_bounds, NULL, NULL, 0, + static_cast(CGBitmapContextGetData(target_context_)), + static_cast(CGBitmapContextGetBytesPerRow(target_context_))); + } + // Create a GWorld for the plugin to paint into whenever it wants; since + // QuickDraw plugins don't draw at known times, they can't be allowed to draw + // directly into the shared memory. + NewGWorld(&plugin_world_, k32ARGBPixelFormat, &window_bounds, + NULL, NULL, kNativeEndianPixMap); + if (fast_path_enabled_) + current_port_ = plugin_world_; +} + +void QuickDrawDrawingManager::ScrapeWindow(WindowRef window, + CGContextRef target_context, + const gfx::Size& plugin_size) { + if (!target_context) + return; + + CGRect window_bounds = CGRectMake(0, 0, + plugin_size.width(), + plugin_size.height()); + CGWindowID window_id = HIWindowGetCGWindowID(window); + CGContextSaveGState(target_context); + CGContextTranslateCTM(target_context, 0, plugin_size.height()); + CGContextScaleCTM(target_context, 1.0, -1.0); + CGContextCopyWindowCaptureContentsToRect(target_context, window_bounds, + _CGSDefaultConnection(), + window_id, 0); + CGContextRestoreGState(target_context); +} + +void QuickDrawDrawingManager::CopyGWorldBits(GWorldPtr source, GWorldPtr dest, + const gfx::Size& plugin_size) { + if (!(source && dest)) + return; + + Rect window_bounds = { 0, 0, plugin_size.height(), plugin_size.width() }; + PixMapHandle source_pixmap = GetGWorldPixMap(source); + if (LockPixels(source_pixmap)) { + PixMapHandle dest_pixmap = GetGWorldPixMap(dest); + if (LockPixels(dest_pixmap)) { + SetGWorld(dest, NULL); + // Set foreground and background colors to avoid "colorizing" the image. + ForeColor(blackColor); + BackColor(whiteColor); + CopyBits(reinterpret_cast(*source_pixmap), + reinterpret_cast(*dest_pixmap), + &window_bounds, &window_bounds, srcCopy, NULL); + UnlockPixels(dest_pixmap); + } + UnlockPixels(source_pixmap); + } +} + +#endif // !NP_NO_QUICKDRAW diff --git a/webkit/glue/plugins/quickdraw_drawing_manager_mac.h b/webkit/glue/plugins/quickdraw_drawing_manager_mac.h new file mode 100644 index 0000000..8163f92 --- /dev/null +++ b/webkit/glue/plugins/quickdraw_drawing_manager_mac.h @@ -0,0 +1,83 @@ +// 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 WEBKIT_GLUE_QUICKDRAW_DRAWING_MANAGER_MAC_H_ +#define WEBKIT_GLUE_QUICKDRAW_DRAWING_MANAGER_MAC_H_ + +#ifndef NP_NO_QUICKDRAW + +#import + +#include "gfx/rect.h" + +// Plugin helper class encapsulating the details of capturing what a QuickDraw +// drawing model plugin draws, then drawing it into a CGContext. +class QuickDrawDrawingManager { + public: + QuickDrawDrawingManager(); + ~QuickDrawDrawingManager(); + + // Sets the mode used for plugin drawing. If enabled is true the plugin draws + // into a GWorld that's not connected to a window, otherwise the plugin draws + // into our the plugin's dummy window (which is slower, since the call we use + // to scrape the window contents is much more expensive than copying between + // GWorlds). + void SetFastPathEnabled(bool enabled); + + // Returns true if the fast path is currently enabled. + bool IsFastPathEnabled(); + + // Sets the context that the plugin bits should be copied into when + // UpdateContext is called. This object does not retain |context|, so the + // caller must call SetTargetContext again if the context changes. + // If the fast path is currently enabled, this call will cause the port to + // change. + void SetTargetContext(CGContextRef context, const gfx::Size& plugin_size); + + // Sets the window that is used by the plugin. This object does not own the + // window, so the caler must call SetPluginWindow again if the window changes. + void SetPluginWindow(WindowRef window); + + // Updates the target context with the current plugin bits. + void UpdateContext(); + + // Returns the port that the plugin should draw into. This returned port is + // only valid until the next call to SetFastPathEnabled (or SetTargetContext + // while the fast path is enabled). + CGrafPtr port() { return current_port_; } + + // Makes the QuickDraw port current; should be called before calls where the + // plugin might draw. + void MakePortCurrent(); + + private: + // Updates the GWorlds used by the faster path. + void UpdateGWorlds(); + + // Deletes the GWorlds used by the faster path. + void DestroyGWorlds(); + + // Scrapes the contents of the window into the given context. + // Used for the slower path. + static void ScrapeWindow(WindowRef window, CGContextRef target_context, + const gfx::Size& plugin_size); + + // Copies the source GWorld's bits into the target GWorld. + // Used for the faster path. + static void CopyGWorldBits(GWorldPtr source, GWorldPtr dest, + const gfx::Size& plugin_size); + + WindowRef plugin_window_; // Weak reference. + CGContextRef target_context_; // Weak reference. + gfx::Size plugin_size_; + bool fast_path_enabled_; + CGrafPtr current_port_; + // Variables used for the faster path: + GWorldPtr target_world_; // Created lazily; may be NULL. + GWorldPtr plugin_world_; // Created lazily; may be NULL. +}; + +#endif // !NP_NO_QUICKDRAW + +#endif // QUICKDRAW_DRAWING_MANAGER_MAC diff --git a/webkit/glue/plugins/test/Info.plist b/webkit/glue/plugins/test/Info.plist new file mode 100644 index 0000000..37145fd --- /dev/null +++ b/webkit/glue/plugins/test/Info.plist @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + NPAPITestPlugIn + CFBundleIdentifier + org.chromium.npapi_test_plugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + WebPluginDescription + Simple NPAPI plug-in for Chromium unit tests + WebPluginMIMETypes + + application/vnd.npapi-test + + WebPluginExtensions + + npapitest + + WebPluginTypeDescription + test npapi + + + WebPluginName + Chromium NPAPI Test Plugin + + diff --git a/webkit/glue/plugins/test/npapi_constants.cc b/webkit/glue/plugins/test/npapi_constants.cc new file mode 100644 index 0000000..75cc68f --- /dev/null +++ b/webkit/glue/plugins/test/npapi_constants.cc @@ -0,0 +1,10 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/npapi_constants.h" + +namespace NPAPIClient { +const char kTestCompleteCookie[] = "status"; +const char kTestCompleteSuccess[] = "OK"; +} diff --git a/webkit/glue/plugins/test/npapi_constants.h b/webkit/glue/plugins/test/npapi_constants.h new file mode 100644 index 0000000..6570c35 --- /dev/null +++ b/webkit/glue/plugins/test/npapi_constants.h @@ -0,0 +1,19 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Constants for the NPAPI test + +#ifndef WEBKIT_PORT_PLUGINS_TEST_NPAPI_CONSTANTS_H__ +#define WEBKIT_PORT_PLUGINS_TEST_NPAPI_CONSTANTS_H__ + +namespace NPAPIClient { +// The name of the cookie which will be used to communicate between +// the plugin and the test harness. +extern const char kTestCompleteCookie[]; + +// The cookie value which will be sent to the client upon successful +// test. +extern const char kTestCompleteSuccess[]; +} +#endif // WEBKIT_PORT_PLUGINS_TEST_NPAPI_CONSTANTS_H__ diff --git a/webkit/glue/plugins/test/npapi_test.cc b/webkit/glue/plugins/test/npapi_test.cc new file mode 100644 index 0000000..895a842 --- /dev/null +++ b/webkit/glue/plugins/test/npapi_test.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// +// npapitest +// +// This is a NPAPI Plugin Program which is used to test the Browser's NPAPI +// host implementation. It is used in conjunction with the npapi_unittest. +// +// As a NPAPI Plugin, you can invoke it by creating a web page of the following +// type: +// +// +// +// arguments: +// src: This is the initial content which will be sent to the plugin. +// type: Must be "application/vnd.npapi-test" +// name: The testcase to run when invoked +// id: The id of the test being run (for testing concurrent plugins) +// +// The Plugin drives the actual test, calling host functions and validating the +// Host callbacks which it receives. It is the duty of the plugin to record +// all errors. +// +// To indicate test completion, the plugin expects the containing HTML page to +// implement two javascript functions: +// onSuccess(string testname); +// onFailure(string testname, string results); +// The HTML host pages used in this test will then set a document cookie +// which the automated test framework can poll for and discover that the +// test has completed. +// +// +// TESTS +// When the PluginClient receives a NPP_New callback from the browser, +// it looks at the "name" argument which is passed in. It verifies that +// the name matches a known test, and instantiates that test. The test is +// a subclass of PluginTest. +// +// + +#include "base/basictypes.h" + +#if defined(OS_WIN) +#include +#endif + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define EXPORT __attribute__((visibility ("default"))) +#else +#define EXPORT +#endif + +#include "webkit/glue/plugins/test/plugin_client.h" + +#if defined(OS_WIN) +BOOL API_CALL DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) { + return TRUE; +} +#endif + +extern "C" { +EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* pFuncs) { + return NPAPIClient::PluginClient::GetEntryPoints(pFuncs); +} + +EXPORT NPError API_CALL NP_Shutdown() { + return NPAPIClient::PluginClient::Shutdown(); +} + +#if defined(OS_WIN) || defined(OS_MACOSX) +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* npnFuncs) { + return NPAPIClient::PluginClient::Initialize(npnFuncs); +} +#elif defined(OS_POSIX) +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* npnFuncs, + NPPluginFuncs* nppFuncs) { + NPError error = NPAPIClient::PluginClient::Initialize(npnFuncs); + if (error == NPERR_NO_ERROR) { + error = NP_GetEntryPoints(nppFuncs); + } + return error; +} + +EXPORT NPError API_CALL NP_GetValue(NPP instance, NPPVariable variable, + void* value) { + NPError err = NPERR_NO_ERROR; + + switch (variable) { + case NPPVpluginNameString: + *(static_cast(value)) = "NPAPI Test Plugin"; + break; + case NPPVpluginDescriptionString: + *(static_cast(value)) = + "Simple NPAPI plug-in for Chromium unit tests"; + break; + case NPPVpluginNeedsXEmbed: + *(static_cast(value)) = true; + break; + default: + err = NPERR_GENERIC_ERROR; + break; + } + + return err; +} + +EXPORT const char* API_CALL NP_GetMIMEDescription(void) { + // The layout test LayoutTests/fast/js/navigator-mimeTypes-length.html + // asserts that the number of mimetypes handled by plugins should be + // greater than the number of plugins. We specify a mimetype here so + // this plugin has at least one. + return "application/vnd.npapi-test:npapitest:test npapi"; +} +#endif // OS_POSIX +} // extern "C" + +namespace WebCore { + const char* currentTextBreakLocaleID() { return "en_us"; } +} diff --git a/webkit/glue/plugins/test/npapi_test.def b/webkit/glue/plugins/test/npapi_test.def new file mode 100644 index 0000000..4481c16 --- /dev/null +++ b/webkit/glue/plugins/test/npapi_test.def @@ -0,0 +1,6 @@ +LIBRARY npapi_test_plugin + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 diff --git a/webkit/glue/plugins/test/npapi_test.rc b/webkit/glue/plugins/test/npapi_test.rc new file mode 100644 index 0000000..524dda4 --- /dev/null +++ b/webkit/glue/plugins/test/npapi_test.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "FileDescription", "NPAPI Test Plugin" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "npapi_test_plugin" + VALUE "LegalCopyright", "Copyright (C) 2007" + VALUE "MIMEType", "application/vnd.npapi-test" + VALUE "OriginalFilename", "npapi_test_plugin.dll" + VALUE "ProductName", "NPAPI Test Plugin" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/webkit/glue/plugins/test/plugin_arguments_test.cc b/webkit/glue/plugins/test/plugin_arguments_test.cc new file mode 100644 index 0000000..46ccf43 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_arguments_test.cc @@ -0,0 +1,69 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/string_util.h" +#include "base/stringprintf.h" + +#include "webkit/glue/plugins/test/plugin_arguments_test.h" + +namespace NPAPIClient { + +PluginArgumentsTest::PluginArgumentsTest(NPP id, + NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PluginArgumentsTest::New(uint16 mode, int16 argc, + const char* argn[], const char* argv[], + NPSavedData* saved) { + // mode: should be the string either "NP_EMBED" or "NP_FULL", + // depending on the mode passed in. + // count: the count of "val" arguments. If the value is + // 2, then we'll find arguments "val1" and "val2". If + // the value is 0, then there will be no "val" arguments. + // size: each val string will be this size * the value's + // index. E.g if size is "10", val1 will be 10bytes, + // and val2 will be 20bytes. + const char *mode_string = GetArgValue("mode", argc, argn, argv); + ExpectAsciiStringNotEqual(mode_string, (const char *)NULL); + if (mode_string != NULL) { + std::string mode_dep_string = mode_string; + if (mode == NP_EMBED) + ExpectStringLowerCaseEqual(mode_dep_string, "np_embed"); + else if (mode == NP_FULL) + ExpectStringLowerCaseEqual(mode_dep_string, "np_full"); + } + + const char *count_string = GetArgValue("count", argc, argn, argv); + if (count_string != NULL) { + int max_args = atoi(count_string); + + const char *size_string = GetArgValue("size", argc, argn, argv); + ExpectAsciiStringNotEqual(size_string, (const char *)NULL); + if (size_string != NULL) { + int size = atoi(size_string); + + for (int index = 1; index <= max_args; index++) { + std::string arg_name = base::StringPrintf("%s%d", "val", index); + const char *val_string = GetArgValue(arg_name.c_str(), argc, argn, + argv); + ExpectAsciiStringNotEqual(val_string, (const char*)NULL); + if (val_string != NULL) + ExpectIntegerEqual((int)strlen(val_string), (index*size)); + } + } + } + + return PluginTest::New(mode, argc, argn, argv, saved); +} + +NPError PluginArgumentsTest::SetWindow(NPWindow* pNPWindow) { + // This test just tests the arguments. We're done now. + this->SignalTestCompleted(); + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_arguments_test.h b/webkit/glue/plugins/test/plugin_arguments_test.h new file mode 100644 index 0000000..aa05f19 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_arguments_test.h @@ -0,0 +1,43 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_PORT_PLUGINS_TEST_PLUGIN_ARGUMENTS_TEST_H__ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_ARGUMENTS_TEST_H__ + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// The PluginArgumentsTest test that we properly receive arguments +// intended for the plugin. +// +// This is basically overkill for testing that the arguments passed +// to the plugin match what we expect. +// +// We expect to find the following arguments: +// mode: should be the string either "NP_EMBED" or "NP_FULL", +// depending on the mode passed in. +// count: the count of "val" arguments. If the value is +// 2, then we'll find arguments "val1" and "val2". If +// the value is 0, then there will be no "val" arguments. +// size: each val string will be this size * the value's +// index. E.g if size is "10", val1 will be 10bytes, +// and val2 will be 20bytes. +// +class PluginArgumentsTest : public PluginTest { + public: + // Constructor. + PluginArgumentsTest(NPP id, NPNetscapeFuncs *host_functions); + + // Initialize this PluginTest based on the arguments from NPP_New. + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_ARGUMENTS_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_client.cc b/webkit/glue/plugins/test/plugin_client.cc new file mode 100644 index 0000000..8358340 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_client.cc @@ -0,0 +1,240 @@ +// 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 "webkit/glue/plugins/test/plugin_client.h" + +#include "base/string_util.h" +#include "webkit/glue/plugins/test/plugin_test.h" +#include "webkit/glue/plugins/test/plugin_test_factory.h" + +namespace NPAPIClient { + +NPNetscapeFuncs* PluginClient::host_functions_; + +NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) { + if (pFuncs == NULL) + return NPERR_INVALID_FUNCTABLE_ERROR; + + if (pFuncs->size < sizeof(NPPluginFuncs)) + return NPERR_INVALID_FUNCTABLE_ERROR; + + pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + pFuncs->newp = NPP_New; + pFuncs->destroy = NPP_Destroy; + pFuncs->setwindow = NPP_SetWindow; + pFuncs->newstream = NPP_NewStream; + pFuncs->destroystream = NPP_DestroyStream; + pFuncs->asfile = NPP_StreamAsFile; + pFuncs->writeready = NPP_WriteReady; + pFuncs->write = NPP_Write; + pFuncs->print = NPP_Print; + pFuncs->event = NPP_HandleEvent; + pFuncs->urlnotify = NPP_URLNotify; + pFuncs->getvalue = NPP_GetValue; + pFuncs->setvalue = NPP_SetValue; + pFuncs->javaClass = NULL; + pFuncs->urlredirectnotify = NPP_URLRedirectNotify; + + return NPERR_NO_ERROR; +} + +NPError PluginClient::Initialize(NPNetscapeFuncs* pFuncs) { + if (pFuncs == NULL) { + return NPERR_INVALID_FUNCTABLE_ERROR; + } + + if (static_cast((pFuncs->version >> 8) & 0xff) > + NP_VERSION_MAJOR) { + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } + +#if defined(OS_WIN) + // Check if we should crash. + HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit"); + if (WaitForSingleObject(crash_event, 0) == WAIT_OBJECT_0) { + int *zero = NULL; + *zero = 0; + } + CloseHandle(crash_event); +#endif + + host_functions_ = pFuncs; + + return NPERR_NO_ERROR; +} + +NPError PluginClient::Shutdown() { + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient + +extern "C" { +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, + int16 argc, char* argn[], char* argv[], NPSavedData* saved) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + // We look at the test name requested via the plugin arguments. We match + // that against a given test and try to instantiate it. + + // lookup the name parameter + std::string test_name; + for (int name_index = 0; name_index < argc; name_index++) { + if (base::strcasecmp(argn[name_index], "name") == 0) { + test_name = argv[name_index]; + break; + } + } + if (test_name.empty()) + return NPERR_GENERIC_ERROR; // no name found + + NPAPIClient::PluginTest* new_test = NPAPIClient::CreatePluginTest(test_name, + instance, NPAPIClient::PluginClient::HostFunctions()); + if (new_test == NULL) { + // If we don't have a test case for this, create a + // generic one which basically never fails. + LOG(WARNING) << "Unknown test name '" << test_name + << "'; using default test."; + new_test = new NPAPIClient::PluginTest(instance, + NPAPIClient::PluginClient::HostFunctions()); + } + + NPError ret = new_test->New(mode, argc, (const char**)argn, + (const char**)argv, saved); + if ((ret == NPERR_NO_ERROR) && new_test->IsWindowless()) { + NPAPIClient::PluginClient::HostFunctions()->setvalue( + instance, NPPVpluginWindowBool, NULL); + } + + return ret; +} + +NPError NPP_Destroy(NPP instance, NPSavedData** save) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + NPError rv = plugin->Destroy(); + delete plugin; + return rv; +} + +NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->SetWindow(pNPWindow); +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, + NPStream* stream, NPBool seekable, uint16* stype) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->NewStream(type, stream, seekable, stype); +} + +int32 NPP_WriteReady(NPP instance, NPStream *stream) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->WriteReady(stream); +} + +int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, + int32 len, void *buffer) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->Write(stream, offset, len, buffer); +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->DestroyStream(stream, reason); +} + +void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { + if (instance == NULL) + return; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->StreamAsFile(stream, fname); +} + +void NPP_Print(NPP instance, NPPrint* printInfo) { + if (instance == NULL) + return; + + // XXXMB - do work here. +} + +void NPP_URLNotify(NPP instance, const char* url, NPReason reason, + void* notifyData) { + if (instance == NULL) + return; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->URLNotify(url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + // XXXMB - do work here. + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + // XXXMB - do work here. + return NPERR_GENERIC_ERROR; +} + +int16 NPP_HandleEvent(NPP instance, void* event) { + if (instance == NULL) + return 0; + + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + + return plugin->HandleEvent(event); +} + +void NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, + void* notify_data) { + if (instance) { + NPAPIClient::PluginTest* plugin = + reinterpret_cast(instance->pdata); + plugin->URLRedirectNotify(url, status, notify_data); + } +} +} // extern "C" diff --git a/webkit/glue/plugins/test/plugin_client.h b/webkit/glue/plugins/test/plugin_client.h new file mode 100644 index 0000000..a6291b0 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_client.h @@ -0,0 +1,45 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_PORT_PLUGINS_TEST_PLUGIN_CLIENT_H__ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_CLIENT_H__ + +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +namespace NPAPIClient { + +// A PluginClient is a NPAPI Plugin. This class contains +// the bootstrapping functions used by the browser to load +// the plugin. +class PluginClient { + public: + // Although not documented in the NPAPI specification, this function + // gets the list of entry points in the NPAPI Plugin (client) for the + // NPAPI Host to call. + static NPError GetEntryPoints(NPPluginFuncs* pFuncs); + + // The browser calls this function only once: when a plug-in is loaded, + // before the first instance is created. This is the first function that + // the browser calls. NP_Initialize tells the plug-in that the browser has + // loaded it and provides global initialization. Allocate any memory or + // resources shared by all instances of your plug-in at this time. + static NPError Initialize(NPNetscapeFuncs* pFuncs); + + // The browser calls this function once after the last instance of your + // plug-in is destroyed, before unloading the plug-in library itself. Use + // NP_Shutdown to delete any data allocated in NP_Initialize to be shared + // by all instances of a plug-in. + static NPError Shutdown(); + + // The table of functions provided by the host. + static NPNetscapeFuncs *HostFunctions() { return host_functions_; } + + private: + static NPNetscapeFuncs* host_functions_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_CLIENT_H__ diff --git a/webkit/glue/plugins/test/plugin_create_instance_in_paint.cc b/webkit/glue/plugins/test/plugin_create_instance_in_paint.cc new file mode 100644 index 0000000..f98f89b --- /dev/null +++ b/webkit/glue/plugins/test/plugin_create_instance_in_paint.cc @@ -0,0 +1,78 @@ +// 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 "webkit/glue/plugins/test/plugin_create_instance_in_paint.h" + +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +CreateInstanceInPaintTest::CreateInstanceInPaintTest( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + window_(NULL), created_(false) { +} + +NPError CreateInstanceInPaintTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (test_id() == "1") { + if (!window_) { + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS; + wcex.lpfnWndProc = + &NPAPIClient::CreateInstanceInPaintTest::WindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = L"CreateInstanceInPaintTestWindowClass"; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + } + + HWND parent = reinterpret_cast(pNPWindow->window); + window_ = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE , + 0, 0, 100, 100, parent, 0, GetModuleHandle(NULL), 0); + DCHECK(window_); + // TODO: this property leaks. + ::SetProp(window_, L"Plugin_Instance", this); + } + } else if (test_id() == "2") { + SignalTestCompleted(); + } else { + NOTREACHED(); + } + return NPERR_NO_ERROR; +} + +LRESULT CALLBACK CreateInstanceInPaintTest::WindowProc( + HWND window, UINT message, WPARAM wparam, LPARAM lparam) { + if (message == WM_PAINT) { + CreateInstanceInPaintTest* this_instance = + reinterpret_cast + (::GetProp(window, L"Plugin_Instance")); + if (this_instance->test_id() == "1" && !this_instance->created_) { + ::RemoveProp(window, L"Plugin_Instance"); + this_instance->created_ = true; + this_instance->HostFunctions()->geturlnotify( + this_instance->id(), "javascript:CreateNewInstance()", NULL, + reinterpret_cast(1)); + } + } + + return DefWindowProc(window, message, wparam, lparam); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_create_instance_in_paint.h b/webkit/glue/plugins/test/plugin_create_instance_in_paint.h new file mode 100644 index 0000000..84d7a94 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_create_instance_in_paint.h @@ -0,0 +1,33 @@ +// 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 WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_CREATE_INSTANCE_IN_PAINT_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_CREATE_INSTANCE_IN_PAINT_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests that creating a new plugin via script while handling a +// Windows message doesn't cause a deadlock. +class CreateInstanceInPaintTest : public PluginTest { + public: + // Constructor. + CreateInstanceInPaintTest(NPP id, NPNetscapeFuncs *host_functions); + // + // NPAPI functions + // + virtual NPError SetWindow(NPWindow* pNPWindow); + + private: + static LRESULT CALLBACK WindowProc( + HWND window, UINT message, WPARAM wparam, LPARAM lparam); + + HWND window_; + bool created_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_CREATE_INSTANCE_IN_PAINT_H diff --git a/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.cc b/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.cc new file mode 100644 index 0000000..15318b4 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h" + +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +#define kUrl "javascript:window.location+\"\"" +#define kUrlStreamId 1 + +DeletePluginInStreamTest::DeletePluginInStreamTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + test_started_(false) { +} + +NPError DeletePluginInStreamTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (!test_started_) { + std::string url = "self_delete_plugin_stream.html"; + HostFunctions()->geturlnotify(id(), url.c_str(), NULL, + reinterpret_cast(kUrlStreamId)); + test_started_ = true; + } + return NPERR_NO_ERROR; +} + +NPError DeletePluginInStreamTest::NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + NPIdentifier delete_id = HostFunctions()->getstringidentifier("DeletePluginWithinScript"); + + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + + NPVariant rv; + HostFunctions()->invoke(id(), window_obj, delete_id, NULL, 0, &rv); + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h b/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h new file mode 100644 index 0000000..418e976 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h @@ -0,0 +1,30 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_DELETE_PLUGIN_IN_STREAM_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_DELETE_PLUGIN_IN_STREAM_TEST_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests +class DeletePluginInStreamTest : public PluginTest { + public: + // Constructor. + DeletePluginInStreamTest(NPP id, NPNetscapeFuncs *host_functions); + // + // NPAPI functions + // + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + private: + bool test_started_; + std::string self_url_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_DELETE_PLUGIN_IN_STREAM_TEST_H diff --git a/webkit/glue/plugins/test/plugin_get_javascript_url2_test.cc b/webkit/glue/plugins/test/plugin_get_javascript_url2_test.cc new file mode 100644 index 0000000..d17dced --- /dev/null +++ b/webkit/glue/plugins/test/plugin_get_javascript_url2_test.cc @@ -0,0 +1,134 @@ +// Copyright (c) 2006-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 "webkit/glue/plugins/test/plugin_get_javascript_url2_test.h" + +#include "base/basictypes.h" + +// url for "self". +#define SELF_URL "javascript:window.location+\"\"" +// The identifier for the self url stream. +#define SELF_URL_STREAM_ID 1 + +// The identifier for the fetched url stream. +#define FETCHED_URL_STREAM_ID 2 + +// The maximum chunk size of stream data. +#define STREAM_CHUNK 197 + +const int kNPNEvaluateTimerID = 100; +const int kNPNEvaluateTimerElapse = 50; + +namespace NPAPIClient { + +ExecuteGetJavascriptUrl2Test::ExecuteGetJavascriptUrl2Test( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + test_started_(false) { +} + +NPError ExecuteGetJavascriptUrl2Test::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (!test_started_) { + std::string url = SELF_URL; + HostFunctions()->geturlnotify(id(), url.c_str(), "_self", + reinterpret_cast(SELF_URL_STREAM_ID)); + test_started_ = true; + } + return NPERR_NO_ERROR; +} + +NPError ExecuteGetJavascriptUrl2Test::NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +int32 ExecuteGetJavascriptUrl2Test::WriteReady(NPStream *stream) { + return STREAM_CHUNK; +} + +int32 ExecuteGetJavascriptUrl2Test::Write(NPStream *stream, int32 offset, int32 len, + void *buffer) { + if (stream == NULL) { + SetError("Write got null stream"); + return -1; + } + if (len < 0 || len > STREAM_CHUNK) { + SetError("Write got bogus stream chunk size"); + return -1; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + self_url_.append(static_cast(buffer), len); + break; + default: + SetError("Unexpected write callback"); + break; + } + // Pretend that we took all the data. + return len; +} + + +NPError ExecuteGetJavascriptUrl2Test::DestroyStream(NPStream *stream, NPError reason) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + // don't care + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +void ExecuteGetJavascriptUrl2Test::URLNotify(const char* url, NPReason reason, void* data) { + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(data), + cast_validity_check); + + unsigned long stream_id = reinterpret_cast(data); + switch (stream_id) { + case SELF_URL_STREAM_ID: + if (strcmp(url, SELF_URL) != 0) + SetError("URLNotify reported incorrect url for SELF_URL"); + if (self_url_.empty()) + SetError("Failed to obtain window location."); + SignalTestCompleted(); + break; + default: + SetError("Unexpected NewStream callback"); + break; + } +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_get_javascript_url2_test.h b/webkit/glue/plugins/test/plugin_get_javascript_url2_test.h new file mode 100644 index 0000000..557da76 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_get_javascript_url2_test.h @@ -0,0 +1,38 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL2_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL2_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests NPP_GetURLNotify for a javascript URL with _top +// as the target frame. +class ExecuteGetJavascriptUrl2Test : public PluginTest { + public: + // Constructor. + ExecuteGetJavascriptUrl2Test(NPP id, NPNetscapeFuncs *host_functions); + + // + // NPAPI functions + // + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + virtual int32 WriteReady(NPStream *stream); + virtual int32 Write(NPStream *stream, int32 offset, int32 len, + void *buffer); + virtual NPError DestroyStream(NPStream *stream, NPError reason); + virtual void URLNotify(const char* url, NPReason reason, void* data); + + private: + bool test_started_; + std::string self_url_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL2_H diff --git a/webkit/glue/plugins/test/plugin_get_javascript_url_test.cc b/webkit/glue/plugins/test/plugin_get_javascript_url_test.cc new file mode 100644 index 0000000..50f5e5a --- /dev/null +++ b/webkit/glue/plugins/test/plugin_get_javascript_url_test.cc @@ -0,0 +1,218 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_get_javascript_url_test.h" + +#include "base/basictypes.h" + +// url for "self". +#define SELF_URL "javascript:window.location+\"\"" +// The identifier for the self url stream. +#define SELF_URL_STREAM_ID 1 + +// The identifier for the fetched url stream. +#define FETCHED_URL_STREAM_ID 2 + +// The maximum chunk size of stream data. +#define STREAM_CHUNK 197 + +const int kNPNEvaluateTimerID = 100; +const int kNPNEvaluateTimerElapse = 50; + + +namespace NPAPIClient { + +ExecuteGetJavascriptUrlTest::ExecuteGetJavascriptUrlTest( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + test_started_(false), +#ifdef OS_WIN + window_(NULL), +#endif + npn_evaluate_context_(false) { +} + +NPError ExecuteGetJavascriptUrlTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (!test_started_) { + std::string url = SELF_URL; + HostFunctions()->geturlnotify(id(), url.c_str(), "_top", + reinterpret_cast(SELF_URL_STREAM_ID)); + test_started_ = true; + +#ifdef OS_WIN + HWND window_handle = reinterpret_cast(pNPWindow->window); + if (!::GetProp(window_handle, L"Plugin_Instance")) { + // TODO: this propery leaks. + ::SetProp(window_handle, L"Plugin_Instance", this); + // We attempt to retreive the NPObject for the plugin instance identified + // by the NPObjectLifetimeTestInstance2 class as it may not have been + // instantiated yet. + SetTimer(window_handle, kNPNEvaluateTimerID, kNPNEvaluateTimerElapse, + TimerProc); + } + window_ = window_handle; +#endif + } + + return NPERR_NO_ERROR; +} + +#ifdef OS_WIN +void CALLBACK ExecuteGetJavascriptUrlTest::TimerProc( + HWND window, UINT message, UINT timer_id, unsigned long elapsed_time) { + ExecuteGetJavascriptUrlTest* this_instance = + reinterpret_cast + (::GetProp(window, L"Plugin_Instance")); + + ::RemoveProp(window, L"Plugin_Instance"); + + NPObject *window_obj = NULL; + this_instance->HostFunctions()->getvalue(this_instance->id(), + NPNVWindowNPObject, + &window_obj); + if (!window_obj) { + this_instance->SetError("Failed to get NPObject for plugin instance2"); + this_instance->SignalTestCompleted(); + return; + } + + std::string script = "javascript:window.location"; + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = static_cast(script.length()); + NPVariant result_var; + + this_instance->npn_evaluate_context_ = true; + NPError result = this_instance->HostFunctions()->evaluate( + this_instance->id(), window_obj, &script_string, &result_var); + this_instance->npn_evaluate_context_ = false; +} +#endif + +NPError ExecuteGetJavascriptUrlTest::NewStream(NPMIMEType type, + NPStream* stream, + NPBool seekable, + uint16* stype) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + + if (npn_evaluate_context_) { + SetError("NewStream received in context of NPN_Evaluate"); + return NPERR_NO_ERROR; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +int32 ExecuteGetJavascriptUrlTest::WriteReady(NPStream *stream) { + if (npn_evaluate_context_) { + SetError("WriteReady received in context of NPN_Evaluate"); + return NPERR_NO_ERROR; + } + return STREAM_CHUNK; +} + +int32 ExecuteGetJavascriptUrlTest::Write(NPStream *stream, int32 offset, + int32 len, void *buffer) { + if (stream == NULL) { + SetError("Write got null stream"); + return -1; + } + if (len < 0 || len > STREAM_CHUNK) { + SetError("Write got bogus stream chunk size"); + return -1; + } + + if (npn_evaluate_context_) { + SetError("Write received in context of NPN_Evaluate"); + return len; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + self_url_.append(static_cast(buffer), len); + break; + default: + SetError("Unexpected write callback"); + break; + } + // Pretend that we took all the data. + return len; +} + + +NPError ExecuteGetJavascriptUrlTest::DestroyStream(NPStream *stream, + NPError reason) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + +#ifdef OS_WIN + KillTimer(window_, kNPNEvaluateTimerID); +#endif + + if (npn_evaluate_context_) { + SetError("DestroyStream received in context of NPN_Evaluate"); + return NPERR_NO_ERROR; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + // don't care + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +void ExecuteGetJavascriptUrlTest::URLNotify(const char* url, NPReason reason, + void* data) { + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(data), + cast_validity_check); + + if (npn_evaluate_context_) { + SetError("URLNotify received in context of NPN_Evaluate"); + return; + } + + unsigned long stream_id = reinterpret_cast(data); + switch (stream_id) { + case SELF_URL_STREAM_ID: + if (strcmp(url, SELF_URL) != 0) + SetError("URLNotify reported incorrect url for SELF_URL"); + if (self_url_.empty()) + SetError("Failed to obtain window location."); + SignalTestCompleted(); + break; + default: + SetError("Unexpected NewStream callback"); + break; + } +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_get_javascript_url_test.h b/webkit/glue/plugins/test/plugin_get_javascript_url_test.h new file mode 100644 index 0000000..5c2540d --- /dev/null +++ b/webkit/glue/plugins/test/plugin_get_javascript_url_test.h @@ -0,0 +1,47 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests NPP_GetURLNotify for a javascript URL with _top +// as the target frame. +class ExecuteGetJavascriptUrlTest : public PluginTest { + public: + // Constructor. + ExecuteGetJavascriptUrlTest(NPP id, NPNetscapeFuncs *host_functions); + // + // NPAPI functions + // + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + virtual int32 WriteReady(NPStream *stream); + virtual int32 Write(NPStream *stream, int32 offset, int32 len, + void *buffer); + virtual NPError DestroyStream(NPStream *stream, NPError reason); + virtual void URLNotify(const char* url, NPReason reason, void* data); + + private: +#if defined(OS_WIN) + static void CALLBACK TimerProc(HWND window, UINT message, UINT timer_id, + unsigned long elapsed_time); +#endif + bool test_started_; + // This flag is set to true in the context of the NPN_Evaluate call. + bool npn_evaluate_context_; + std::string self_url_; + +#if defined(OS_WIN) + HWND window_; +#endif +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_GET_JAVASCRIPT_URL_H diff --git a/webkit/glue/plugins/test/plugin_geturl_test.cc b/webkit/glue/plugins/test/plugin_geturl_test.cc new file mode 100644 index 0000000..5363a66 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_geturl_test.cc @@ -0,0 +1,414 @@ +// 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 "webkit/glue/plugins/test/plugin_geturl_test.h" + +#include + +#include "base/basictypes.h" +#include "base/file_util.h" +#include "base/string_number_conversions.h" +#include "base/utf_string_conversions.h" + +// url for "self". The %22%22 is to make a statement for javascript to +// evaluate and return. +#define SELF_URL "javascript:window.location+\"\"" + +// The identifier for the self url stream. +#define SELF_URL_STREAM_ID 1 + +// The identifier for the fetched url stream. +#define FETCHED_URL_STREAM_ID 2 + +// url for testing GetURL with a bogus URL. +#define BOGUS_URL "bogoproto:///x:/asdf.xysdhffieasdf.asdhj/" + +// url for testing redirect notifications sent to plugins. +#define REDIRECT_SRC_URL \ + "http://mock.http/npapi/plugin_read_page_redirect_src.html" + +// The notification id for the redirect notification url. +#define REDIRECT_SRC_URL_NOTIFICATION_ID 4 + +// The identifier for the bogus url stream. +#define BOGUS_URL_STREAM_ID 3 + +// The maximum chunk size of stream data. +#define STREAM_CHUNK 197 + +namespace NPAPIClient { + +PluginGetURLTest::PluginGetURLTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + tests_started_(false), + tests_in_progress_(0), + test_file_(NULL), + expect_404_response_(false), + npn_evaluate_context_(false), + handle_url_redirects_(false), + received_url_redirect_notification_(false) { +} + +NPError PluginGetURLTest::New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved) { + const char* page_not_found_url = GetArgValue("page_not_found_url", argc, + argn, argv); + if (page_not_found_url) { + page_not_found_url_ = page_not_found_url; + expect_404_response_ = true; + } + + const char* fail_write_url = GetArgValue("fail_write_url", argc, + argn, argv); + if (fail_write_url) { + fail_write_url_ = fail_write_url; + } + + const char* referrer_target_url = GetArgValue("ref_target", argc, + argn, argv); + if (referrer_target_url) { + referrer_target_url_ = referrer_target_url; + } + + if (!base::strcasecmp(GetArgValue("name", argc, argn, argv), + "geturlredirectnotify")) { + handle_url_redirects_ = true; + } + return PluginTest::New(mode, argc, argn, argv, saved); +} + +NPError PluginGetURLTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (!tests_started_) { + tests_started_ = true; + + tests_in_progress_++; + + if (expect_404_response_) { + HostFunctions()->geturl(id(), page_not_found_url_.c_str(), NULL); + return NPERR_NO_ERROR; + } else if (!fail_write_url_.empty()) { + HostFunctions()->geturl(id(), fail_write_url_.c_str(), NULL); + return NPERR_NO_ERROR; + } else if (!referrer_target_url_.empty()) { + HostFunctions()->pushpopupsenabledstate(id(), true); + HostFunctions()->geturl(id(), referrer_target_url_.c_str(), "_blank"); + HostFunctions()->poppopupsenabledstate(id()); + return NPERR_NO_ERROR; + } else if (handle_url_redirects_) { + HostFunctions()->geturlnotify( + id(), REDIRECT_SRC_URL, NULL, + reinterpret_cast(REDIRECT_SRC_URL_NOTIFICATION_ID)); + return NPERR_NO_ERROR; + } + + std::string url = SELF_URL; + HostFunctions()->geturlnotify(id(), url.c_str(), NULL, + reinterpret_cast(SELF_URL_STREAM_ID)); + + tests_in_progress_++; + std::string bogus_url = BOGUS_URL; + HostFunctions()->geturlnotify(id(), bogus_url.c_str(), NULL, + reinterpret_cast(BOGUS_URL_STREAM_ID)); + } + return NPERR_NO_ERROR; +} + +NPError PluginGetURLTest::NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + + if (test_completed()) { + return PluginTest::NewStream(type, stream, seekable, stype); + } + + if (!referrer_target_url_.empty()) { + return NPERR_NO_ERROR; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + + if (expect_404_response_) { + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + if (!window_obj) { + SetError("Failed to get NPObject for plugin instance2"); + SignalTestCompleted(); + return NPERR_NO_ERROR; + } + + std::string script = "javascript:alert('Hi there from plugin');"; + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = static_cast(script.length()); + NPVariant result_var; + + npn_evaluate_context_ = true; + HostFunctions()->evaluate(id(), window_obj, &script_string, &result_var); + npn_evaluate_context_ = false; + return NPERR_NO_ERROR; + } + + if (!fail_write_url_.empty()) { + return NPERR_NO_ERROR; + } + + + unsigned long stream_id = reinterpret_cast( + stream->notifyData); + + switch (stream_id) { + case SELF_URL_STREAM_ID: + break; + case FETCHED_URL_STREAM_ID: + { + std::string filename = self_url_; + if (filename.find("file:///", 0) != 0) { + SetError("Test expects a file-url."); + break; + } + + // TODO(evanm): use the net:: functions to convert file:// URLs to + // on-disk file paths. But it probably doesn't actually matter in + // this test. + +#if defined(OS_WIN) + filename = filename.substr(8); // remove "file:///" + // Assume an ASCII path on Windows. + FilePath path = FilePath(ASCIIToWide(filename)); +#else + filename = filename.substr(7); // remove "file://" + FilePath path = FilePath(filename); +#endif + + test_file_ = file_util::OpenFile(path, "r"); + if (!test_file_) { + SetError("Could not open source file"); + } + } + break; + case BOGUS_URL_STREAM_ID: + SetError("Unexpected NewStream for BOGUS_URL"); + break; + case REDIRECT_SRC_URL_NOTIFICATION_ID: + SetError("Should not redirect to URL when plugin denied it."); + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +int32 PluginGetURLTest::WriteReady(NPStream *stream) { + if (test_completed()) { + return PluginTest::WriteReady(stream); + } + + if (!referrer_target_url_.empty()) { + return STREAM_CHUNK; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast( + stream->notifyData); + if (stream_id == BOGUS_URL_STREAM_ID) + SetError("Received WriteReady for BOGUS_URL"); + + return STREAM_CHUNK; +} + +int32 PluginGetURLTest::Write(NPStream *stream, int32 offset, int32 len, + void *buffer) { + if (test_completed()) { + return PluginTest::Write(stream, offset, len, buffer); + } + + if (!fail_write_url_.empty()) { + SignalTestCompleted(); + return -1; + } + + if (!referrer_target_url_.empty()) { + return len; + } + + if (stream == NULL) { + SetError("Write got null stream"); + return -1; + } + if (len < 0 || len > STREAM_CHUNK) { + SetError("Write got bogus stream chunk size"); + return -1; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = reinterpret_cast( + stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + self_url_.append(static_cast(buffer), len); + break; + case FETCHED_URL_STREAM_ID: + { + char read_buffer[STREAM_CHUNK]; + int32 bytes = fread(read_buffer, 1, len, test_file_); + // Technically, fread could return fewer than len + // bytes. But this is not likely. + if (bytes != len) + SetError("Did not read correct bytelength from source file"); + if (memcmp(read_buffer, buffer, len)) + SetError("Content mismatch between data and source!"); + } + break; + case BOGUS_URL_STREAM_ID: + SetError("Unexpected write callback for BOGUS_URL"); + break; + default: + SetError("Unexpected write callback"); + break; + } + // Pretend that we took all the data. + return len; +} + + +NPError PluginGetURLTest::DestroyStream(NPStream *stream, NPError reason) { + if (test_completed()) { + return PluginTest::DestroyStream(stream, reason); + } + + if (stream == NULL) { + SetError("NewStream got null stream"); + return NPERR_INVALID_PARAM; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + + if (expect_404_response_) { + if (npn_evaluate_context_) { + SetError("Received destroyStream in the context of NPN_Evaluate."); + } + + SignalTestCompleted(); + return NPERR_NO_ERROR; + } + + if (!referrer_target_url_.empty()) { + return NPERR_NO_ERROR; + } + + unsigned long stream_id = + reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + // don't care + break; + case FETCHED_URL_STREAM_ID: + { + char read_buffer[STREAM_CHUNK]; + size_t bytes = fread(read_buffer, 1, sizeof(read_buffer), test_file_); + if (bytes != 0) + SetError("Data and source mismatch on length"); + file_util::CloseFile(test_file_); + } + break; + default: + SetError("Unexpected NewStream callback"); + break; + } + return NPERR_NO_ERROR; +} + +void PluginGetURLTest::StreamAsFile(NPStream* stream, const char* fname) { + if (stream == NULL) { + SetError("NewStream got null stream"); + return; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(stream->notifyData), + cast_validity_check); + unsigned long stream_id = + reinterpret_cast(stream->notifyData); + switch (stream_id) { + case SELF_URL_STREAM_ID: + // don't care + break; + default: + SetError("Unexpected NewStream callback"); + break; + } +} + +void PluginGetURLTest::URLNotify(const char* url, NPReason reason, void* data) { + if (!tests_in_progress_) { + SetError("URLNotify received after tests completed"); + return; + } + + if (!url) { + SetError("URLNotify received NULL url"); + return; + } + + COMPILE_ASSERT(sizeof(unsigned long) <= sizeof(data), cast_validity_check); + unsigned long stream_id = reinterpret_cast(data); + switch (stream_id) { + case SELF_URL_STREAM_ID: + if (strcmp(url, SELF_URL) != 0) + SetError("URLNotify reported incorrect url for SELF_URL"); + + // We have our stream url. Go fetch it. + HostFunctions()->geturlnotify(id(), self_url_.c_str(), NULL, + reinterpret_cast(FETCHED_URL_STREAM_ID)); + break; + case FETCHED_URL_STREAM_ID: + if (!url || strcmp(url, self_url_.c_str()) != 0) + SetError("URLNotify reported incorrect url for FETCHED_URL"); + tests_in_progress_--; + break; + case BOGUS_URL_STREAM_ID: + if (reason != NPRES_NETWORK_ERR) { + std::string err = "BOGUS_URL received unexpected URLNotify status: "; + err.append(base::IntToString(reason)); + SetError(err); + } + tests_in_progress_--; + break; + case REDIRECT_SRC_URL_NOTIFICATION_ID: { + if (!received_url_redirect_notification_) { + SetError("Failed to receive URLRedirect notification"); + } + tests_in_progress_--; + break; + } + default: + SetError("Unexpected NewStream callback"); + break; + } + + if (tests_in_progress_ == 0) + SignalTestCompleted(); +} + +void PluginGetURLTest::URLRedirectNotify(const char* url, + int32_t status, + void* notify_data) { + if (!base::strcasecmp(url, "http://mock.http/npapi/plugin_read_page.html")) { + received_url_redirect_notification_ = true; + // Disallow redirect notification. + HostFunctions()->urlredirectresponse(id(), notify_data, false); + } +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_geturl_test.h b/webkit/glue/plugins/test/plugin_geturl_test.h new file mode 100644 index 0000000..df8d741 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_geturl_test.h @@ -0,0 +1,61 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_PORT_PLUGINS_TEST_PLUGIN_GETURL_TEST_H__ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_GETURL_TEST_H__ + +#include + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// The PluginGetURLTest test functionality of the NPN_GetURL +// and NPN_GetURLNotify methods. +// +// This test first discovers it's URL by sending a GetURL request +// for 'javascript:top.location'. After receiving that, the +// test will request the url itself (again via GetURL). +class PluginGetURLTest : public PluginTest { + public: + // Constructor. + PluginGetURLTest(NPP id, NPNetscapeFuncs *host_functions); + + // + // NPAPI functions + // + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + virtual int32 WriteReady(NPStream *stream); + virtual int32 Write(NPStream *stream, int32 offset, int32 len, + void *buffer); + virtual NPError DestroyStream(NPStream *stream, NPError reason); + virtual void StreamAsFile(NPStream* stream, const char* fname); + virtual void URLNotify(const char* url, NPReason reason, void* data); + virtual void URLRedirectNotify(const char* url, int32_t status, + void* notify_data); + + private: + bool tests_started_; + int tests_in_progress_; + std::string self_url_; + FILE* test_file_; + bool expect_404_response_; + // This flag is set to true in the context of the NPN_Evaluate call. + bool npn_evaluate_context_; + // The following two flags handle URL redirect notifications received by + // plugins. + bool handle_url_redirects_; + bool received_url_redirect_notification_; + std::string page_not_found_url_; + std::string fail_write_url_; + std::string referrer_target_url_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_GETURL_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_javascript_open_popup.cc b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc new file mode 100644 index 0000000..0f93bf4 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "build/build_config.h" +#include "webkit/glue/plugins/test/plugin_javascript_open_popup.h" + +#if defined(USE_X11) +#include "third_party/npapi/bindings/npapi_x11.h" +#endif +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +ExecuteJavascriptOpenPopupWithPluginTest:: + ExecuteJavascriptOpenPopupWithPluginTest(NPP id, + NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + popup_window_test_started_(false) { +} + +int16 ExecuteJavascriptOpenPopupWithPluginTest::SetWindow( + NPWindow* window) { + if (window->window == NULL) + return NPERR_NO_ERROR; + + if (!popup_window_test_started_) { + popup_window_test_started_ = true; + HostFunctions()->geturl( + id(), "popup_window_with_target_plugin.html", "_blank"); + } + return NPERR_NO_ERROR; +} + +// ExecuteJavascriptPopupWindowTargetPluginTest member defines. +ExecuteJavascriptPopupWindowTargetPluginTest:: + ExecuteJavascriptPopupWindowTargetPluginTest( + NPP id, NPNetscapeFuncs* host_functions) + : PluginTest(id, host_functions), + test_completed_(false) { +} + +int16 ExecuteJavascriptPopupWindowTargetPluginTest::SetWindow( + NPWindow* window) { + if (window->window == NULL) + return NPERR_NO_ERROR; + + if (!test_completed_) { + if (CheckWindow(window)) { + SignalTestCompleted(); + test_completed_ = true; + } + } + return PluginTest::SetWindow(window); +} + +#if defined(OS_WIN) +bool ExecuteJavascriptPopupWindowTargetPluginTest::CheckWindow( + NPWindow* window) { + HWND window_handle = reinterpret_cast(window->window); + + if (IsWindow(window_handle)) { + HWND parent_window = GetParent(window_handle); + if (!IsWindow(parent_window) || parent_window == GetDesktopWindow()) + SetError("Windowed plugin instantiated with NULL parent"); + return true; + } + + return false; +} + +#elif defined(USE_X11) +// This code blindly follows the same sorts of verifications done on +// the Windows side. Does it make sense on X? Maybe not really, but +// it can't hurt to do extra validations. +bool ExecuteJavascriptPopupWindowTargetPluginTest::CheckWindow( + NPWindow* window) { + Window xwindow = reinterpret_cast(window->window); + // Grab a pointer to the extra SetWindow data so we can grab the display out. + NPSetWindowCallbackStruct* extra = + static_cast(window->ws_info); + + if (xwindow) { + Window root, parent; + Status status = XQueryTree(extra->display, xwindow, &root, &parent, + NULL, NULL); // NULL children info. + DCHECK(status != 0); + if (!parent || parent == root) + SetError("Windowed plugin instantiated with NULL parent"); + return true; + } + + return false; +} +#elif defined(OS_MACOSX) +bool ExecuteJavascriptPopupWindowTargetPluginTest::CheckWindow( + NPWindow* window) { + // TODO(port) scaffolding--replace with a real test once NPWindow is done. + return false; +} +#endif + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_javascript_open_popup.h b/webkit/glue/plugins/test/plugin_javascript_open_popup.h new file mode 100644 index 0000000..552397a --- /dev/null +++ b/webkit/glue/plugins/test/plugin_javascript_open_popup.h @@ -0,0 +1,47 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests the case where a windowed plugin instance is +// instantiated in a popup window. The plugin instance needs to +// have a valid parent window. +class ExecuteJavascriptOpenPopupWithPluginTest : public PluginTest { + public: + // Constructor. + ExecuteJavascriptOpenPopupWithPluginTest( + NPP id, NPNetscapeFuncs *host_functions); + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* window); + + private: + bool popup_window_test_started_; +}; + +// This class represents a windowed plugin instance instantiated within a +// popup window. It verifies that the plugin instance has a valid parent. +class ExecuteJavascriptPopupWindowTargetPluginTest : public PluginTest { + public: + ExecuteJavascriptPopupWindowTargetPluginTest( + NPP id, NPNetscapeFuncs *host_functions); + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* window); + + private: + // Do a platform-specific validation of the passed-in |window|. + // E.g. on Windows, verifies window->window is a reasonable HWND. + // Returns true if the test should be marked complete. + bool CheckWindow(NPWindow* window); + + bool test_completed_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H diff --git a/webkit/glue/plugins/test/plugin_new_fails_test.cc b/webkit/glue/plugins/test/plugin_new_fails_test.cc new file mode 100644 index 0000000..2feeec6 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_new_fails_test.cc @@ -0,0 +1,18 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_new_fails_test.h" + +namespace NPAPIClient { + +NewFailsTest::NewFailsTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError NewFailsTest::New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved) { + return NPERR_GENERIC_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_new_fails_test.h b/webkit/glue/plugins/test/plugin_new_fails_test.h new file mode 100644 index 0000000..1acf9e5 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_new_fails_test.h @@ -0,0 +1,21 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_PLUGIN_NEW_FAILS_TEST_H__ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_PLUGIN_NEW_FAILS_TEST_H__ + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +class NewFailsTest : public PluginTest { + public: + NewFailsTest(NPP id, NPNetscapeFuncs *host_functions); + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_PLUGIN_NPP_NEW_FAILS_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc new file mode 100644 index 0000000..4564506 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc @@ -0,0 +1,174 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h" + +namespace NPAPIClient { + +const int kNPObjectLifetimeTimer = 100; +const int kNPObjectLifetimeTimerElapse = 2000; + +NPObject* NPObjectLifetimeTestInstance2::plugin_instance_object_ = NULL; + +NPObjectDeletePluginInNPN_Evaluate* + NPObjectDeletePluginInNPN_Evaluate::g_npn_evaluate_test_instance_ = NULL; + +NPObjectLifetimeTest::NPObjectLifetimeTest(NPP id, + NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + other_plugin_instance_object_(NULL), + timer_id_(0) { +} + +NPError NPObjectLifetimeTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + HWND window_handle = reinterpret_cast(pNPWindow->window); + if (!::GetProp(window_handle, L"Plugin_Instance")) { + // TODO: this propery leaks. + ::SetProp(window_handle, L"Plugin_Instance", this); + // We attempt to retreive the NPObject for the plugin instance identified + // by the NPObjectLifetimeTestInstance2 class as it may not have been + // instantiated yet. + timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, + kNPObjectLifetimeTimerElapse, TimerProc); + } + return NPERR_NO_ERROR; +} + +void CALLBACK NPObjectLifetimeTest::TimerProc( + HWND window, UINT message, UINT timer_id, + unsigned long elapsed_milli_seconds) { + + NPObjectLifetimeTest* this_instance = + reinterpret_cast + (::GetProp(window, L"Plugin_Instance")); + KillTimer(window, this_instance->timer_id_); + ::RemoveProp(window, L"Plugin_Instance"); + + this_instance->timer_id_ = 0; + + this_instance->other_plugin_instance_object_ = + NPObjectLifetimeTestInstance2::plugin_instance_object_; + this_instance->HostFunctions()->retainobject( + this_instance->other_plugin_instance_object_); + + NPString script; + script.UTF8Characters = "javascript:DeleteSecondPluginInstance()"; + script.UTF8Length = static_cast(strlen(script.UTF8Characters)); + + this_instance->HostFunctions()->geturlnotify( + this_instance->id(), "javascript:DeleteSecondPluginInstance()", NULL, + reinterpret_cast(1)); +} + +void NPObjectLifetimeTest::URLNotify(const char* url, NPReason reason, + void* data) { + // Create a "location" identifier. + NPIdentifier identifier = HostFunctions()->getstringidentifier("location"); + // Declare a local variant value. + NPVariant variantValue; + // Get the location property from the window object (which is another object). + bool b1 = HostFunctions()->getproperty(id(), other_plugin_instance_object_, + identifier, &variantValue ); + HostFunctions()->releaseobject(other_plugin_instance_object_); + other_plugin_instance_object_ = NULL; + // If this test failed, then we'd have crashed by now. + SignalTestCompleted(); +} + +NPObjectLifetimeTestInstance2::NPObjectLifetimeTestInstance2( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPObjectLifetimeTestInstance2::~NPObjectLifetimeTestInstance2() { + if (plugin_instance_object_) { + HostFunctions()->releaseobject(plugin_instance_object_); + plugin_instance_object_ = NULL; + } +} + +NPError NPObjectLifetimeTestInstance2::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (!plugin_instance_object_) { + if (!HostFunctions()->getvalue(id(), NPNVWindowNPObject, + &plugin_instance_object_)) { + SetError("Failed to get NPObject for plugin instance2"); + SignalTestCompleted(); + return NPERR_GENERIC_ERROR; + } + } + + return NPERR_NO_ERROR; +} + + +NPObjectDeletePluginInNPN_Evaluate::NPObjectDeletePluginInNPN_Evaluate( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + plugin_instance_object_(NULL), + timer_id_(0) { + g_npn_evaluate_test_instance_ = this; +} + +NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() { + if (plugin_instance_object_) { + HostFunctions()->releaseobject(plugin_instance_object_); + plugin_instance_object_ = NULL; + } +} + +NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) { + if (np_window->window == NULL) + return NPERR_NO_ERROR; + + HWND window_handle = reinterpret_cast(np_window->window); + // We setup a timerproc to invoke NPN_Evaluate to destroy this plugin + // instance. This is to ensure that we don't destroy the plugin instance + // while it is being used in webkit as this leads to crashes and is a + // more accurate representation of the renderer crash as described in + // http://b/issue?id=1134683. + if (!timer_id_) { + timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, + kNPObjectLifetimeTimerElapse, TimerProc); + } + return NPERR_NO_ERROR; +} + +void CALLBACK NPObjectDeletePluginInNPN_Evaluate::TimerProc( + HWND window, UINT message, UINT timer_id, + unsigned long elapsed_milli_seconds) { + + KillTimer(window, g_npn_evaluate_test_instance_->timer_id_); + g_npn_evaluate_test_instance_->timer_id_ = 0; + NPObject *window_obj = NULL; + g_npn_evaluate_test_instance_->HostFunctions()->getvalue( + g_npn_evaluate_test_instance_->id(), NPNVWindowNPObject, + &window_obj); + + if (!window_obj) { + g_npn_evaluate_test_instance_->SetError( + "Failed to get NPObject for plugin instance2"); + g_npn_evaluate_test_instance_->SignalTestCompleted(); + return; + } + + std::string script = "javascript:DeletePluginWithinScript()"; + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = + static_cast(script.length()); + + NPVariant result_var; + bool result = g_npn_evaluate_test_instance_->HostFunctions()->evaluate( + g_npn_evaluate_test_instance_->id(), window_obj, + &script_string, &result_var); + // If this test failed we would have crashed by now. +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h new file mode 100644 index 0000000..60d0314 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_LIFETIME_TEST_H__ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_LIFETIME_TEST_H__ + +#include "build/build_config.h" +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// The NPObjectLifeTime class tests the case where a plugin has an NPObject +// which points to a different plugin instance on a different frame in the +// page and whether refcounts on this npobject are valid when the source frame +// is destroyed. +class NPObjectLifetimeTest : public PluginTest { + public: + // Constructor. + NPObjectLifetimeTest(NPP id, NPNetscapeFuncs *host_functions); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); + + virtual void URLNotify(const char* url, NPReason reason, void* data); + + protected: + NPObject* other_plugin_instance_object_; + +#if defined(OS_WIN) + static void CALLBACK TimerProc(HWND window, UINT message, UINT timer_id, + unsigned long elapsed_milli_seconds); + UINT_PTR timer_id_; +#endif + DISALLOW_IMPLICIT_CONSTRUCTORS(NPObjectLifetimeTest); +}; + +// The NPObjectLifetimeTestInstance2 class represents the plugin instance +// which is deleted by the NPObjectLifeTime class via a javascript function. +class NPObjectLifetimeTestInstance2 : public PluginTest { + public: + // Constructor. + NPObjectLifetimeTestInstance2(NPP id, NPNetscapeFuncs *host_functions); + ~NPObjectLifetimeTestInstance2(); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); + protected: + static NPObject* plugin_instance_object_; + friend class NPObjectLifetimeTest; + + DISALLOW_IMPLICIT_CONSTRUCTORS(NPObjectLifetimeTestInstance2); +}; + +// The NPObjectLifeTime class tests the case where a plugin instance is +// destroyed in NPN_Evaluate +class NPObjectDeletePluginInNPN_Evaluate : public PluginTest { + public: + // Constructor. + NPObjectDeletePluginInNPN_Evaluate(NPP id, NPNetscapeFuncs *host_functions); + ~NPObjectDeletePluginInNPN_Evaluate(); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); + + protected: + NPObject* plugin_instance_object_; +#if defined(OS_WIN) + static void CALLBACK TimerProc(HWND window, UINT message, UINT timer_id, + unsigned long elapsed_milli_seconds); + UINT_PTR timer_id_; +#endif + + private: + static NPObjectDeletePluginInNPN_Evaluate* g_npn_evaluate_test_instance_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(NPObjectDeletePluginInNPN_Evaluate); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_LIFETIME_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_npobject_proxy_test.cc b/webkit/glue/plugins/test/plugin_npobject_proxy_test.cc new file mode 100644 index 0000000..5b3a2ca --- /dev/null +++ b/webkit/glue/plugins/test/plugin_npobject_proxy_test.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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 "base/compiler_specific.h" + +#if defined(OS_WIN) +#define STRSAFE_NO_DEPRECATE +#include +#endif +#include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h" + +namespace NPAPIClient { + +NPObjectProxyTest::NPObjectProxyTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError NPObjectProxyTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + NPIdentifier document_id = HostFunctions()->getstringidentifier("document"); + NPIdentifier create_text_node_id = HostFunctions()->getstringidentifier("createTextNode"); + NPIdentifier append_child_id = HostFunctions()->getstringidentifier("appendChild"); + + NPVariant docv; + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + + HostFunctions()->getproperty(id(), window_obj, document_id, &docv); + NPObject *doc = NPVARIANT_TO_OBJECT(docv); + + NPVariant strv; + MSVC_SUPPRESS_WARNING(4267); + STRINGZ_TO_NPVARIANT("div", strv); + + NPVariant textv; + HostFunctions()->invoke(id(), doc, create_text_node_id, &strv, 1, &textv); + + NPVariant v; + HostFunctions()->invoke(id(), doc, append_child_id, &textv, 1, &v); + + // If this test failed, then we'd have crashed by now. + SignalTestCompleted(); + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_npobject_proxy_test.h b/webkit/glue/plugins/test/plugin_npobject_proxy_test.h new file mode 100644 index 0000000..3d14ddb --- /dev/null +++ b/webkit/glue/plugins/test/plugin_npobject_proxy_test.h @@ -0,0 +1,27 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_PROXY_TEST_H__ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_PROXY_TEST_H__ + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// The NPObjectProxyTest tests that when we proxy an NPObject that is itself +// a proxy, we don't create a new proxy but instead just use the original +// pointer. + +class NPObjectProxyTest : public PluginTest { + public: + // Constructor. + NPObjectProxyTest(NPP id, NPNetscapeFuncs *host_functions); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_NPOBJECT_PROXY_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_private_test.cc b/webkit/glue/plugins/test/plugin_private_test.cc new file mode 100644 index 0000000..cdab7ce --- /dev/null +++ b/webkit/glue/plugins/test/plugin_private_test.cc @@ -0,0 +1,57 @@ +// 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 "webkit/glue/plugins/test/plugin_private_test.h" + +#include "base/basictypes.h" +#include "base/string_util.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +PrivateTest::PrivateTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PrivateTest::New(uint16 mode, int16 argc, + const char* argn[], const char* argv[], + NPSavedData* saved) { + PluginTest::New(mode, argc, argn, argv, saved); + + NPBool private_mode = 0; + NPNetscapeFuncs* browser = NPAPIClient::PluginClient::HostFunctions(); + NPError result = browser->getvalue( + id(), NPNVprivateModeBool, &private_mode); + if (result != NPERR_NO_ERROR) { + SetError("Failed to read NPNVprivateModeBool value."); + } else { + NPIdentifier location = HostFunctions()->getstringidentifier("location"); + NPIdentifier href = HostFunctions()->getstringidentifier("href"); + + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + + NPVariant location_var; + HostFunctions()->getproperty(id(), window_obj, location, &location_var); + + NPVariant href_var; + HostFunctions()->getproperty(id(), NPVARIANT_TO_OBJECT(location_var), href, + &href_var); + std::string href_str(href_var.value.stringValue.UTF8Characters, + href_var.value.stringValue.UTF8Length); + bool private_expected = href_str.find("?private") != href_str.npos; + if (private_mode != static_cast(private_expected)) + SetError("NPNVprivateModeBool returned incorrect value."); + + HostFunctions()->releasevariantvalue(&href_var); + HostFunctions()->releasevariantvalue(&location_var); + HostFunctions()->releaseobject(window_obj); + } + + SignalTestCompleted(); + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_private_test.h b/webkit/glue/plugins/test/plugin_private_test.h new file mode 100644 index 0000000..db6b5d1 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_private_test.h @@ -0,0 +1,25 @@ +// 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 WEBKIT_PORT_PLUGINS_TEST_PLUGIN_PRIVATE_TEST_H_ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_PRIVATE_TEST_H_ + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// The PluginPrivateTest tests that a plugin can query if the browser is in +// private browsing mode. +class PrivateTest : public PluginTest { + public: + PrivateTest(NPP id, NPNetscapeFuncs *host_functions); + + // Initialize this PluginTest based on the arguments from NPP_New. + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_PRIVATE_TEST_H_ diff --git a/webkit/glue/plugins/test/plugin_schedule_timer_test.cc b/webkit/glue/plugins/test/plugin_schedule_timer_test.cc new file mode 100644 index 0000000..fbfce34 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_schedule_timer_test.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_schedule_timer_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +using base::Time; + +namespace NPAPIClient { + +// The times below are accurate but they are not tested against because it +// might make the test flakey. +ScheduleTimerTest::Event + ScheduleTimerTest::schedule_[ScheduleTimerTest::kNumEvents] = { + { 0, -1, 0, 100, false, -1 }, // schedule 0 100ms no-repeat + { 100, 0, 0, 200, false, -1 }, // schedule 0 200ms no-repeat + { 300, 0, 0, 100, true, -1 }, // schedule 0 100ms repeat + { 400, 0, 1, 50, true, -1 }, // schedule 1 50ms repeat + { 450, 1, -1, 0, true, -1 }, // receive 1 repeating + { 500, 0, -1, 0, true, -1 }, // receive 0 repeating + { 500, 1, -1, 0, true, -1 }, // receive 1 repeating + { 550, 1, -1, 0, true, -1 }, // receive 1 repeating + { 600, 0, -1, 0, true, 0 }, // receive 0 repeating and unschedule + { 600, 1, 2, 400, true, 1 }, // receive 1 repeating and unschedule + { 1000, 2, -1, 0, true, 2 }, // receive final and unschedule +}; + +ScheduleTimerTest::ScheduleTimerTest( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + num_received_events_(0) { + for (int i = 0; i < kNumTimers; ++i) { + timer_ids_[i] = 0; + } + for (int i = 0; i < kNumEvents; ++i) { + received_events_[i] = false; + } +} + +NPError ScheduleTimerTest::New( + uint16 mode, int16 argc, const char* argn[], const char* argv[], + NPSavedData* saved) { + NPError error = PluginTest::New(mode, argc, argn, argv, saved); + if (error != NPERR_NO_ERROR) + return error; + + start_time_ = Time::Now(); + HandleEvent(0); + + return NPERR_NO_ERROR; +} + +void ScheduleTimerTest::OnTimer(uint32 timer_id) { + Time current_time = Time::Now(); + int relative_time = static_cast( + (current_time - start_time_).InMilliseconds()); + + // See if there is a matching unreceived event. + int event_index = FindUnreceivedEvent(relative_time, timer_id); + if (event_index < 0) { + SetError("Received unexpected timer event"); + SignalTestCompleted(); + return; + } + + HandleEvent(event_index); + + // Finish test if all events have happened. + if (num_received_events_ == kNumEvents) + SignalTestCompleted(); +} + +int ScheduleTimerTest::FindUnreceivedEvent(int time, uint32 timer_id) { + for (int i = 0; i < kNumEvents; ++i) { + const Event& event = schedule_[i]; + if (!received_events_[i] && + timer_ids_[event.received_index] == timer_id) { + return i; + } + } + return -1; +} + +namespace { +void OnTimerHelper(NPP id, uint32 timer_id) { + ScheduleTimerTest* plugin_object = + static_cast(id->pdata); + if (plugin_object) { + plugin_object->OnTimer(timer_id); + } +} +} + +void ScheduleTimerTest::HandleEvent(int event_index) { + const Event& event = schedule_[event_index]; + + // Mark event as received. + DCHECK(!received_events_[event_index]); + received_events_[event_index] = true; + ++num_received_events_; + + // Unschedule timer if present. + if (event.unscheduled_index >= 0) { + HostFunctions()->unscheduletimer( + id(), timer_ids_[event.unscheduled_index]); + } + + // Schedule timer if present. + if (event.scheduled_index >= 0) { + timer_ids_[event.scheduled_index] = HostFunctions()->scheduletimer( + id(), event.scheduled_interval, event.schedule_repeated, OnTimerHelper); + } +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_schedule_timer_test.h b/webkit/glue/plugins/test/plugin_schedule_timer_test.h new file mode 100644 index 0000000..e3e6505a --- /dev/null +++ b/webkit/glue/plugins/test/plugin_schedule_timer_test.h @@ -0,0 +1,68 @@ +// 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 WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SCHEDULE_TIMER_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SCHEDULE_TIMER_TEST_H + +#include "base/at_exit.h" +#include "base/time.h" +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests scheduling and unscheduling of timers using +// NPN_ScheduleTimer and NPN_UnscheduleTimer. +class ScheduleTimerTest : public PluginTest { + public: + ScheduleTimerTest(NPP id, NPNetscapeFuncs *host_functions); + + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + + void OnTimer(uint32 timer_id); + + private: + // base::Time needs one of these. + base::AtExitManager at_exit_manager_; + + // Table mapping timer index (as used in event schedule) to timer id. + static const int kNumTimers = 3; + uint32 timer_ids_[kNumTimers]; + + // Schedule of events for test. + static const int kNumEvents = 11; + struct Event { + int time; + + // The index of the timer that triggered the event or -1 for the first + // event. + int received_index; + + // The index of the timer to schedule on this event or -1. + int scheduled_index; + + // Info about the timer to be scheduled (if any). + uint32 scheduled_interval; + bool schedule_repeated; + + // The index of the timer to unschedule on this event or -1. + int unscheduled_index; + }; + static Event schedule_[kNumEvents]; + int num_received_events_; + + // Set of events that have been received (by index). + bool received_events_[kNumEvents]; + + // Time of initial event. + base::Time start_time_; + + // Returns index of matching unreceived event or -1 if not found. + int FindUnreceivedEvent(int time, uint32 timer_id); + void HandleEvent(int event_index); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SCHEDULE_TIMER_TEST_H diff --git a/webkit/glue/plugins/test/plugin_setup_test.cc b/webkit/glue/plugins/test/plugin_setup_test.cc new file mode 100644 index 0000000..e4c4903 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_setup_test.cc @@ -0,0 +1,22 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/string_util.h" + +#include "webkit/glue/plugins/test/plugin_setup_test.h" + +namespace NPAPIClient { + +PluginSetupTest::PluginSetupTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PluginSetupTest::SetWindow(NPWindow* pNPWindow) { + this->SignalTestCompleted(); + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_setup_test.h b/webkit/glue/plugins/test/plugin_setup_test.h new file mode 100644 index 0000000..b01bc42 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_setup_test.h @@ -0,0 +1,24 @@ +// 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 WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SETUP_TEST_H__ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SETUP_TEST_H__ + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// A very simple test that just sets up a new plug-in. +class PluginSetupTest : public PluginTest { + public: + // Constructor. + PluginSetupTest(NPP id, NPNetscapeFuncs *host_functions); + + // NPAPI SetWindow handler. + virtual NPError SetWindow(NPWindow* pNPWindow); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_SETUP_TEST_H__ diff --git a/webkit/glue/plugins/test/plugin_test.cc b/webkit/glue/plugins/test/plugin_test.cc new file mode 100644 index 0000000..6717e4b --- /dev/null +++ b/webkit/glue/plugins/test/plugin_test.cc @@ -0,0 +1,155 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_test.h" + +#include "base/string_util.h" +#include "webkit/glue/plugins/test/npapi_constants.h" + +namespace NPAPIClient { + +PluginTest::PluginTest(NPP id, NPNetscapeFuncs *host_functions) { + id_ = id; + id_->pdata = this; + host_functions_ = host_functions; + test_completed_ = false; +} + +NPError PluginTest::New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved) { + test_name_ = this->GetArgValue("name", argc, argn, argv); + test_id_ = this->GetArgValue("id", argc, argn, argv); + return NPERR_NO_ERROR; +} + +NPError PluginTest::Destroy() { + return NPERR_NO_ERROR; +} + +NPError PluginTest::SetWindow(NPWindow* pNPWindow) { + return NPERR_NO_ERROR; +} + +// It's a shame I have to implement URLEncode. But, using webkit's +// or using chrome's means a ball of string of dlls and dependencies that +// is very very long. After spending far too much time on it, +// I'll just encode it myself. Too bad Microsoft doesn't implement +// this in a reusable way either. Both webkit and chrome will +// end up using libicu, which is a string of dependencies we don't +// want. + +inline unsigned char toHex(const unsigned char x) { + return x > 9 ? (x + 'A' - 10) : (x + '0'); +} + +std::string URLEncode(const std::string &sIn) { + std::string sOut; + + const size_t length = sIn.length(); + for (size_t idx = 0; idx < length;) { + const char ch = sIn.at(idx); + if (isalnum(ch)) { + sOut.append(1, ch); + } else if (isspace(ch) && ((ch != '\n') && (ch != '\r'))) { + sOut.append(1, '+'); + } else { + sOut.append(1, '%'); + sOut.append(1, toHex(ch>>4)); + sOut.append(1, toHex(ch%16)); + } + idx++; + } + return sOut; +} + +void PluginTest::SignalTestCompleted() { + NPObject *window_obj = NULL; + host_functions_->getvalue(id_, NPNVWindowNPObject, &window_obj); + if (!window_obj) + return; + + test_completed_ = true; + // To signal test completion, we expect a couple of + // javascript functions to be defined in the webpage + // which hosts this plugin: + // onSuccess(test_name, test_id) + // onFailure(test_name, test_id, error_message) + std::string script("javascript:"); + if (Succeeded()) { + script.append("onSuccess(\""); + script.append(test_name_); + script.append("\",\""); + script.append(test_id_); + script.append("\");"); + } else { + script.append("onFailure(\""); + script.append(test_name_); + script.append("\",\""); + script.append(test_id_); + script.append("\",\""); + script.append(test_status_); + script.append("\");"); + } + + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = static_cast(script.length()); + + NPVariant result_var; + host_functions_->evaluate(id_, window_obj, &script_string, &result_var); +} + +const char *PluginTest::GetArgValue(const char *name, const int16 argc, + const char *argn[], const char *argv[]) { + for (int idx = 0; idx < argc; idx++) + if (base::strcasecmp(argn[idx], name) == 0) + return argv[idx]; + return NULL; +} + +void PluginTest::SetError(const std::string &msg) { + test_status_.append(msg); +} + +NPError PluginTest::NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + // There is no default action here. + return NPERR_NO_ERROR; +} + +int32 PluginTest::WriteReady(NPStream *stream) { + // Take data in small chunks + return 4096; +} + +int32 PluginTest::Write(NPStream *stream, int32 offset, int32 len, + void *buffer) { + // Pretend that we took all the data. + return len; +} + +NPError PluginTest::DestroyStream(NPStream *stream, NPError reason) { + // There is no default action. + return NPERR_NO_ERROR; +} + +void PluginTest::StreamAsFile(NPStream* stream, const char* fname) { + // There is no default action. +} + +void PluginTest::URLNotify(const char* url, NPReason reason, void* data) { + // There is no default action +} + +int16 PluginTest::HandleEvent(void* event) { + // There is no default action + return 0; +} + +void PluginTest::URLRedirectNotify(const char* url, int32_t status, + void* notify_data) { + // There is no default action +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_test.h b/webkit/glue/plugins/test/plugin_test.h new file mode 100644 index 0000000..f3f8937 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_test.h @@ -0,0 +1,134 @@ +// 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 WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ + +#include + +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +namespace NPAPIClient { + +// A PluginTest represents an instance of the plugin, which in +// our case is a test case. +class PluginTest { + public: + // Constructor. + PluginTest(NPP id, NPNetscapeFuncs *host_functions); + + // Destructor + virtual ~PluginTest() {} + + // Returns true if the test runs in windowless plugin mode. + virtual bool IsWindowless() const { return false; } + + // + // NPAPI Functions + // + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + virtual NPError Destroy(); + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + virtual int32 WriteReady(NPStream *stream); + virtual int32 Write(NPStream *stream, int32 offset, int32 len, + void *buffer); + virtual NPError DestroyStream(NPStream *stream, NPError reason); + virtual void StreamAsFile(NPStream* stream, const char* fname); + virtual void URLNotify(const char* url, NPReason reason, void* data); + virtual int16 HandleEvent(void* event); + virtual void URLRedirectNotify(const char* url, int32_t status, + void* notify_data); + // Returns true if the test has not had any errors. + bool Succeeded() { return test_status_.length() == 0; } + + // Sets an error for the test case. Appends the msg to the + // error that will be returned from the test. + void SetError(const std::string &msg); + + // Expect two string values are equal, and if not, logs an + // appropriate error about it. + void ExpectStringLowerCaseEqual(const std::string &val1, const std::string &val2) { + if (!LowerCaseEqualsASCII(val1, val2.c_str())) { + std::string err; + err = "Expected Equal for '"; + err.append(val1); + err.append("' and '"); + err.append(val2); + err.append("'"); + SetError(err); + } + }; + + // Expect two values to not be equal, and if they are + // logs an appropriate error about it. + void ExpectAsciiStringNotEqual(const char *val1, const char *val2) { + if (val1 == val2) { + std::string err; + err = "Expected Not Equal for '"; + err.append(val1); + err.append("' and '"); + err.append(val2); + err.append("'"); + SetError(err); + } + } + // Expect two integer values are equal, and if not, logs an + // appropriate error about it. + void ExpectIntegerEqual(int val1, int val2) { + if (val1 != val2) { + std::string err; + err = "Expected Equal for '"; + err.append(base::IntToString(val1)); + err.append("' and '"); + err.append(base::IntToString(val2)); + err.append("'"); + SetError(err); + } + } + + + protected: + // Signals to the Test that invoked us that the test is + // completed. This is done by forcing the plugin to + // set a cookie in the browser window, which the test program + // is waiting for. Note - because this is done by + // using javascript, the browser must have the frame + // setup before the plugin calls this function. So plugin + // tests MUST NOT call this function prior to having + // received the SetWindow() callback from the browser. + void SignalTestCompleted(); + + // Helper function to lookup names in the input array. + // If the name is found, returns the value, otherwise + // returns NULL. + const char *GetArgValue(const char *name, const int16 argc, + const char *argn[], const char *argv[]); + + // Access to the list of functions provided + // by the NPAPI host. + NPNetscapeFuncs *HostFunctions() { return host_functions_; } + + // The NPP Identifier for this plugin instance. + NPP id() { return id_; } + std::string test_id() const { return test_id_; } + std::string test_name() const { return test_name_; } + bool test_completed() const { return test_completed_; } + private: + NPP id_; + NPNetscapeFuncs * host_functions_; + std::string test_name_; + std::string test_id_; + std::string test_status_; + bool test_completed_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_H_ diff --git a/webkit/glue/plugins/test/plugin_test_factory.cc b/webkit/glue/plugins/test/plugin_test_factory.cc new file mode 100644 index 0000000..b4ae4f1 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_test_factory.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_test_factory.h" + +#include "webkit/glue/plugins/test/plugin_arguments_test.h" +#include "webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h" +#include "webkit/glue/plugins/test/plugin_get_javascript_url_test.h" +#include "webkit/glue/plugins/test/plugin_get_javascript_url2_test.h" +#include "webkit/glue/plugins/test/plugin_geturl_test.h" +#include "webkit/glue/plugins/test/plugin_javascript_open_popup.h" +#include "webkit/glue/plugins/test/plugin_new_fails_test.h" +#include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h" +#include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h" +#include "webkit/glue/plugins/test/plugin_private_test.h" +#include "webkit/glue/plugins/test/plugin_schedule_timer_test.h" +#include "webkit/glue/plugins/test/plugin_setup_test.h" +#include "webkit/glue/plugins/test/plugin_thread_async_call_test.h" +#include "webkit/glue/plugins/test/plugin_window_size_test.h" +#if defined(OS_WIN) +#include "webkit/glue/plugins/test/plugin_windowed_test.h" +#endif +#include "webkit/glue/plugins/test/plugin_windowless_test.h" + +namespace NPAPIClient { + +PluginTest* CreatePluginTest(const std::string& test_name, + NPP instance, + NPNetscapeFuncs* host_functions) { + PluginTest* new_test = NULL; + + if (test_name == "arguments") { + new_test = new PluginArgumentsTest(instance, host_functions); + } else if (test_name == "geturl" || test_name == "geturl_404_response" || + test_name == "geturl_fail_write" || + test_name == "plugin_referrer_test" || + test_name == "geturlredirectnotify") { + new_test = new PluginGetURLTest(instance, host_functions); + } else if (test_name == "npobject_proxy") { + new_test = new NPObjectProxyTest(instance, host_functions); +#if defined(OS_WIN) || defined(OS_MACOSX) + // TODO(port): plugin_windowless_test.*. + } else if (test_name == "execute_script_delete_in_paint" || + test_name == "execute_script_delete_in_mouse_move" || + test_name == "delete_frame_test" || + test_name == "multiple_instances_sync_calls" || + test_name == "no_hang_if_init_crashes" || + test_name == "convert_point") { + new_test = new WindowlessPluginTest(instance, host_functions); +#endif + } else if (test_name == "getjavascripturl") { + new_test = new ExecuteGetJavascriptUrlTest(instance, host_functions); + } else if (test_name == "getjavascripturl2") { + new_test = new ExecuteGetJavascriptUrl2Test(instance, host_functions); +#if defined(OS_WIN) + // TODO(port): plugin_window_size_test.*. + } else if (test_name == "checkwindowrect") { + new_test = new PluginWindowSizeTest(instance, host_functions); +#endif + } else if (test_name == "self_delete_plugin_stream") { + new_test = new DeletePluginInStreamTest(instance, host_functions); +#if defined(OS_WIN) + // TODO(port): plugin_npobject_lifetime_test.*. + } else if (test_name == "npobject_lifetime_test") { + new_test = new NPObjectLifetimeTest(instance, host_functions); + } else if (test_name == "npobject_lifetime_test_second_instance") { + new_test = new NPObjectLifetimeTestInstance2(instance, host_functions); + } else if (test_name == "new_fails") { + new_test = new NewFailsTest(instance, host_functions); + } else if (test_name == "npobject_delete_plugin_in_evaluate" || + test_name == "npobject_delete_create_plugin_in_evaluate") { + new_test = new NPObjectDeletePluginInNPN_Evaluate(instance, host_functions); +#endif + } else if (test_name == "plugin_javascript_open_popup_with_plugin") { + new_test = new ExecuteJavascriptOpenPopupWithPluginTest( + instance, host_functions); + } else if (test_name == "plugin_popup_with_plugin_target") { + new_test = new ExecuteJavascriptPopupWindowTargetPluginTest( + instance, host_functions); + } else if (test_name == "plugin_thread_async_call") { + new_test = new PluginThreadAsyncCallTest(instance, host_functions); + } else if (test_name == "private") { + new_test = new PrivateTest(instance, host_functions); + } else if (test_name == "schedule_timer") { + new_test = new ScheduleTimerTest(instance, host_functions); +#if defined(OS_WIN) + // TODO(port): plugin_windowed_test.*. + } else if (test_name == "hidden_plugin" || + test_name == "create_instance_in_paint" || + test_name == "alert_in_window_message" || + test_name == "ensure_scripting_works_in_destroy" || + test_name == "invoke_js_function_on_create") { + new_test = new WindowedPluginTest(instance, host_functions); +#endif + } else if (test_name == "setup") { + // "plugin" is the name for plugin documents. + new_test = new PluginSetupTest(instance, host_functions); + } + + return new_test; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_test_factory.h b/webkit/glue/plugins/test/plugin_test_factory.h new file mode 100644 index 0000000..3fd38d5 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_test_factory.h @@ -0,0 +1,22 @@ +// 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 WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_FACTROY_H__ +#define WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_FACTROY_H__ + +#include + +#include "third_party/npapi/bindings/nphostapi.h" + +namespace NPAPIClient { + +class PluginTest; + +extern PluginTest* CreatePluginTest(const std::string& test_name, + NPP instance, + NPNetscapeFuncs* host_functions); + +} // namespace NPAPIClient + +#endif // WEBKIT_PORT_PLUGINS_TEST_PLUGIN_TEST_FACTROY_H__ diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.cc b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc new file mode 100644 index 0000000..c01a49e --- /dev/null +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc @@ -0,0 +1,117 @@ +// 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 "webkit/glue/plugins/test/plugin_thread_async_call_test.h" + +#include "base/at_exit.h" +#include "base/message_loop.h" +#include "base/thread.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +namespace { + +// There are two plugin instances in this test. The long lived instance is used +// for reporting errors and signalling test completion. The short lived one is +// used to verify that async callbacks are not invoked after NPP_Destroy. +PluginThreadAsyncCallTest* g_short_lived_instance; +PluginThreadAsyncCallTest* g_long_lived_instance; + +void OnCallSucceededHelper(void* data) { + static_cast(data)->OnCallSucceeded(); +} + +class AsyncCallTask : public Task { + public: + AsyncCallTask(PluginThreadAsyncCallTest* test_class) + : test_class_(test_class) {} + + void Run() { + test_class_->AsyncCall(); + } + + private: + PluginThreadAsyncCallTest* test_class_; +}; + +void OnCallFailed(void* data) { + g_long_lived_instance->SetError("Async callback invoked after NPP_Destroy"); +} + +void OnCallCompletedHelper(void* data) { + static_cast(data)->OnCallCompleted(); +} +} + +PluginThreadAsyncCallTest::PluginThreadAsyncCallTest( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PluginThreadAsyncCallTest::New( + uint16 mode, int16 argc, const char* argn[], const char* argv[], + NPSavedData* saved) { + NPError error = PluginTest::New(mode, argc, argn, argv, saved); + if (error != NPERR_NO_ERROR) + return error; + + // Determine whether this is the short lived instance. + for (int i = 0; i < argc; ++i) { + if (base::strcasecmp(argn[i], "short_lived") == 0) { + if (base::strcasecmp(argv[i], "true") == 0) { + g_short_lived_instance = this; + } else { + g_long_lived_instance = this; + } + } + } + + // Schedule an async call that will succeed. Make sure to call that API from + // a different thread to fully test it. + if (this == g_short_lived_instance) { + at_exit_manager_.reset(new base::AtExitManager()); + base::Thread random_thread("random_thread"); + random_thread.Start(); + random_thread.message_loop()->PostTask(FROM_HERE, new AsyncCallTask(this)); + } + + return NPERR_NO_ERROR; +} + +void PluginThreadAsyncCallTest::AsyncCall() { + HostFunctions()->pluginthreadasynccall(id(), OnCallSucceededHelper, this); +} + +void PluginThreadAsyncCallTest::OnCallSucceeded() { + // Delete the short lived instance. + NPIdentifier delete_id = HostFunctions()->getstringidentifier( + "deleteShortLivedInstance"); + + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + + NPVariant result; + HostFunctions()->invoke(id(), window_obj, delete_id, NULL, 0, &result); +} + +NPError PluginThreadAsyncCallTest::Destroy() { + if (this == g_short_lived_instance) { + // Schedule an async call that should not be called. + HostFunctions()->pluginthreadasynccall(id(), OnCallFailed, NULL); + + // Schedule an async call to end the test using the long lived instance. + HostFunctions()->pluginthreadasynccall(g_long_lived_instance->id(), + OnCallCompletedHelper, + g_long_lived_instance); + } + + return NPERR_NO_ERROR; +} + +void PluginThreadAsyncCallTest::OnCallCompleted() { + SignalTestCompleted(); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.h b/webkit/glue/plugins/test/plugin_thread_async_call_test.h new file mode 100644 index 0000000..78e4e8d --- /dev/null +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.h @@ -0,0 +1,39 @@ +// 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 WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ + +#include "base/scoped_ptr.h" +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace base { +class AtExitManager; +} + +namespace NPAPIClient { + +// This class tests scheduling and unscheduling of async callbacks using +// NPN_PluginThreadAsyncCall. +class PluginThreadAsyncCallTest : public PluginTest { + public: + PluginThreadAsyncCallTest(NPP id, NPNetscapeFuncs *host_functions); + + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + + virtual NPError Destroy(); + + void AsyncCall(); + void OnCallSucceeded(); + void OnCallCompleted(); + + private: + // base::Thread needs one of these. + scoped_ptr at_exit_manager_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H_ diff --git a/webkit/glue/plugins/test/plugin_window_size_test.cc b/webkit/glue/plugins/test/plugin_window_size_test.cc new file mode 100644 index 0000000..9bfabca --- /dev/null +++ b/webkit/glue/plugins/test/plugin_window_size_test.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/test/plugin_window_size_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +PluginWindowSizeTest::PluginWindowSizeTest(NPP id, + NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PluginWindowSizeTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + HWND window = reinterpret_cast(pNPWindow->window); + if (!pNPWindow || !::IsWindow(window)) { + SetError("Invalid arguments passed in"); + return NPERR_INVALID_PARAM; + } + + RECT window_rect = {0}; + window_rect.left = pNPWindow->x; + window_rect.top = pNPWindow->y; + window_rect.right = pNPWindow->width; + window_rect.bottom = pNPWindow->height; + + if (!::IsRectEmpty(&window_rect)) { + RECT client_rect = {0}; + ::GetClientRect(window, &client_rect); + if (::IsRectEmpty(&client_rect)) { + SetError("The client rect of the plugin window is empty. Test failed"); + } + + // Bug 6742: ensure that the coordinates passed in are relative to the + // parent HWND. + POINT origin_from_os; + RECT window_rect_from_os; + ::GetWindowRect(window, &window_rect_from_os); + origin_from_os.x = window_rect_from_os.left; + origin_from_os.y = window_rect_from_os.top; + ::ScreenToClient(GetParent(window), &origin_from_os); + if (origin_from_os.x != pNPWindow->x || origin_from_os.y != pNPWindow->y) + SetError("Wrong position passed in to SetWindow! Test failed"); + + SignalTestCompleted(); + } + + return NPERR_NO_ERROR; +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_window_size_test.h b/webkit/glue/plugins/test/plugin_window_size_test.h new file mode 100644 index 0000000..3650671 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_window_size_test.h @@ -0,0 +1,24 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_WINDOW_SIZE_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_WINDOW_SIZE_TEST_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests whether the plugin window has a non zero rect +// on the second SetWindow call. +class PluginWindowSizeTest : public PluginTest { + public: + // Constructor. + PluginWindowSizeTest(NPP id, NPNetscapeFuncs *host_functions); + // NPAPI SetWindow handler + virtual NPError SetWindow(NPWindow* pNPWindow); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_WINDOW_SIZE_TEST_H diff --git a/webkit/glue/plugins/test/plugin_windowed_test.cc b/webkit/glue/plugins/test/plugin_windowed_test.cc new file mode 100644 index 0000000..c82aa55 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowed_test.cc @@ -0,0 +1,150 @@ +// 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 "webkit/glue/plugins/test/plugin_windowed_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +WindowedPluginTest::WindowedPluginTest(NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions), + window_(NULL), done_(false) { +} + +WindowedPluginTest::~WindowedPluginTest() { + if (window_) + DestroyWindow(window_); +} + +NPError WindowedPluginTest::SetWindow(NPWindow* pNPWindow) { + if (pNPWindow->window == NULL) + return NPERR_NO_ERROR; + + if (test_name() == "create_instance_in_paint" && test_id() == "2") { + SignalTestCompleted(); + return NPERR_NO_ERROR; + } + + if (window_) + return NPERR_NO_ERROR; + + HWND parent = reinterpret_cast(pNPWindow->window); + if (!pNPWindow || !::IsWindow(parent)) { + SetError("Invalid arguments passed in"); + return NPERR_INVALID_PARAM; + } + + if ((test_name() == "create_instance_in_paint" && test_id() == "1") || + test_name() == "alert_in_window_message" || + test_name() == "invoke_js_function_on_create") { + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS; + wcex.lpfnWndProc = &NPAPIClient::WindowedPluginTest::WindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = L"CreateInstanceInPaintTestWindowClass"; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + } + + window_ = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE , + 0, 0, 100, 100, parent, 0, GetModuleHandle(NULL), 0); + DCHECK(window_); + // TODO: this propery leaks. + ::SetProp(window_, L"Plugin_Instance", this); + } + + return NPERR_NO_ERROR; +} + +NPError WindowedPluginTest::Destroy() { + if (test_name() != "ensure_scripting_works_in_destroy") + return NPERR_NO_ERROR; + + // Bug 23706: ensure that scripting works with no asserts. + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject,&window_obj); + + if (!window_obj) { + SetError("Failed to get NPObject for plugin instance"); + } else { + std::string script = "javascript:GetMagicNumber()"; + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = + static_cast(script.length()); + + NPVariant result_var; + bool result = HostFunctions()->evaluate( + id(), window_obj, &script_string, &result_var); + if (!result || + result_var.type != NPVariantType_Double || + result_var.value.doubleValue != 42.0) { + SetError("Failed to script during NPP_Destroy"); + } + } + + SignalTestCompleted(); + return NPERR_NO_ERROR; +} + +void WindowedPluginTest::CallJSFunction( + WindowedPluginTest* this_ptr, const char* function) { + NPIdentifier function_id = this_ptr->HostFunctions()->getstringidentifier( + function); + + NPObject *window_obj = NULL; + this_ptr->HostFunctions()->getvalue( + this_ptr->id(), NPNVWindowNPObject, &window_obj); + + NPVariant rv; + this_ptr->HostFunctions()->invoke( + this_ptr->id(), window_obj, function_id, NULL, 0, &rv); +} + +LRESULT CALLBACK WindowedPluginTest::WindowProc( + HWND window, UINT message, WPARAM wparam, LPARAM lparam) { + WindowedPluginTest* this_ptr = + reinterpret_cast + (::GetProp(window, L"Plugin_Instance")); + + if (this_ptr && !this_ptr->done_) { + if (this_ptr->test_name() == "create_instance_in_paint" && + message == WM_PAINT) { + this_ptr->done_ = true; + CallJSFunction(this_ptr, "CreateNewInstance"); + } else if (this_ptr->test_name() == "alert_in_window_message" && + message == WM_PAINT) { + this_ptr->done_ = true; + // We call this function twice as we want to display two alerts + // and verify that we don't hang the browser. + CallJSFunction(this_ptr, "CallAlert"); + CallJSFunction(this_ptr, "CallAlert"); + } else if (this_ptr->test_name() == + "invoke_js_function_on_create" && + message == WM_PAINT) { + this_ptr->done_ = true; + CallJSFunction(this_ptr, "PluginCreated"); + } + + if (this_ptr->done_) { + ::RemoveProp(window, L"Plugin_Instance"); + } + } + + return DefWindowProc(window, message, wparam, lparam); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_windowed_test.h b/webkit/glue/plugins/test/plugin_windowed_test.h new file mode 100644 index 0000000..949ea86 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowed_test.h @@ -0,0 +1,33 @@ +// 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 WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_WINDOWED_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_WINDOWED_TEST_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class contains a list of windowed plugin tests. Please add additional +// tests to this class. +class WindowedPluginTest : public PluginTest { + public: + WindowedPluginTest(NPP id, NPNetscapeFuncs *host_functions); + ~WindowedPluginTest(); + + private: + static LRESULT CALLBACK WindowProc( + HWND window, UINT message, WPARAM wparam, LPARAM lparam); + static void CallJSFunction(WindowedPluginTest*, const char*); + + virtual NPError SetWindow(NPWindow* pNPWindow); + virtual NPError Destroy(); + + HWND window_; + bool done_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_WINDOWED_TEST_H diff --git a/webkit/glue/plugins/test/plugin_windowless_test.cc b/webkit/glue/plugins/test/plugin_windowless_test.cc new file mode 100644 index 0000000..aa6a9d7 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowless_test.cc @@ -0,0 +1,261 @@ +// 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. + +#define STRSAFE_NO_DEPRECATE +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "webkit/glue/plugins/test/plugin_windowless_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +#if defined(OS_MACOSX) +#include +#include +#endif + +namespace NPAPIClient { + +// Remember the first plugin instance for tests involving multiple instances +WindowlessPluginTest* g_other_instance = NULL; + +WindowlessPluginTest::WindowlessPluginTest(NPP id, + NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { + if (!g_other_instance) + g_other_instance = this; +} + +static bool IsPaintEvent(NPEvent* np_event) { +#if defined(OS_WIN) + return WM_PAINT == np_event->event; +#elif defined(OS_MACOSX) + return np_event->what == updateEvt; +#endif +} + +static bool IsMouseMoveEvent(NPEvent* np_event) { +#if defined(OS_WIN) + return WM_MOUSEMOVE == np_event->event; +#elif defined(OS_MACOSX) + return np_event->what == nullEvent; +#endif +} + +static bool IsMouseUpEvent(NPEvent* np_event) { +#if defined(OS_WIN) + return WM_LBUTTONUP == np_event->event; +#elif defined(OS_MACOSX) + return np_event->what == mouseUp; +#endif +} + +static bool IsWindowActivationEvent(NPEvent* np_event) { +#if defined(OS_WIN) + NOTIMPLEMENTED(); + return false; +#elif defined(OS_MACOSX) + return np_event->what == activateEvt; +#endif +} + +int16 WindowlessPluginTest::HandleEvent(void* event) { + + NPNetscapeFuncs* browser = NPAPIClient::PluginClient::HostFunctions(); + + NPBool supports_windowless = 0; + NPError result = browser->getvalue(id(), NPNVSupportsWindowless, + &supports_windowless); + if ((result != NPERR_NO_ERROR) || (supports_windowless != TRUE)) { + SetError("Failed to read NPNVSupportsWindowless value"); + SignalTestCompleted(); + return PluginTest::HandleEvent(event); + } + + NPEvent* np_event = reinterpret_cast(event); + if (IsPaintEvent(np_event)) { +#if defined(OS_WIN) + HDC paint_dc = reinterpret_cast(np_event->wParam); + if (paint_dc == NULL) { + SetError("Invalid Window DC passed to HandleEvent for WM_PAINT"); + SignalTestCompleted(); + return NPERR_GENERIC_ERROR; + } + + HRGN clipping_region = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(paint_dc, clipping_region)) { + SetError("No clipping region set in window DC"); + DeleteObject(clipping_region); + SignalTestCompleted(); + return NPERR_GENERIC_ERROR; + } + + DeleteObject(clipping_region); +#endif + + if (test_name() == "execute_script_delete_in_paint") { + ExecuteScriptDeleteInPaint(browser); + } else if (test_name() == "multiple_instances_sync_calls") { + MultipleInstanceSyncCalls(browser); + } +#if OS_MACOSX + } else if (IsWindowActivationEvent(np_event) && + test_name() == "convert_point") { + ConvertPoint(browser); +#endif + } else if (IsMouseMoveEvent(np_event) && + test_name() == "execute_script_delete_in_mouse_move") { + ExecuteScript(browser, id(), "DeletePluginWithinScript();", NULL); + SignalTestCompleted(); + } else if (IsMouseUpEvent(np_event) && + test_name() == "delete_frame_test") { + ExecuteScript( + browser, id(), + "parent.document.getElementById('frame').outerHTML = ''", NULL); + } + // If this test failed, then we'd have crashed by now. + return PluginTest::HandleEvent(event); +} + +NPError WindowlessPluginTest::ExecuteScript(NPNetscapeFuncs* browser, NPP id, + const std::string& script, NPVariant* result) { + std::string script_url = "javascript:"; + script_url += script; + + NPString script_string = { script_url.c_str(), script_url.length() }; + NPObject *window_obj = NULL; + browser->getvalue(id, NPNVWindowNPObject, &window_obj); + + NPVariant unused_result; + if (!result) + result = &unused_result; + + return browser->evaluate(id, window_obj, &script_string, result); +} + +void WindowlessPluginTest::ExecuteScriptDeleteInPaint( + NPNetscapeFuncs* browser) { + const NPUTF8* urlString = "javascript:DeletePluginWithinScript()"; + const NPUTF8* targetString = NULL; + browser->geturl(id(), urlString, targetString); + SignalTestCompleted(); +} + +void WindowlessPluginTest::MultipleInstanceSyncCalls(NPNetscapeFuncs* browser) { + if (this == g_other_instance) + return; + + DCHECK(g_other_instance); + ExecuteScript(browser, g_other_instance->id(), "TestCallback();", NULL); + SignalTestCompleted(); +} + +#if defined(OS_MACOSX) +std::string StringForPoint(int x, int y) { + std::string point_string("("); + point_string.append(base::IntToString(x)); + point_string.append(", "); + point_string.append(base::IntToString(y)); + point_string.append(")"); + return point_string; +} +#endif + +void WindowlessPluginTest::ConvertPoint(NPNetscapeFuncs* browser) { +#if defined(OS_MACOSX) + // First, just sanity-test that round trips work. + NPCoordinateSpace spaces[] = { NPCoordinateSpacePlugin, + NPCoordinateSpaceWindow, + NPCoordinateSpaceFlippedWindow, + NPCoordinateSpaceScreen, + NPCoordinateSpaceFlippedScreen }; + for (unsigned int i = 0; i < arraysize(spaces); ++i) { + for (unsigned int j = 0; j < arraysize(spaces); ++j) { + double x, y, round_trip_x, round_trip_y; + if (!(browser->convertpoint(id(), 0, 0, spaces[i], &x, &y, spaces[j])) || + !(browser->convertpoint(id(), x, y, spaces[j], &round_trip_x, + &round_trip_y, spaces[i]))) { + SetError("Conversion failed"); + SignalTestCompleted(); + return; + } + if (i != j && x == 0 && y == 0) { + SetError("Converting a coordinate should change it"); + SignalTestCompleted(); + return; + } + if (round_trip_x != 0 || round_trip_y != 0) { + SetError("Round-trip conversion should return the original point"); + SignalTestCompleted(); + return; + } + } + } + + // Now, more extensive testing on a single point. + double screen_x, screen_y; + browser->convertpoint(id(), 0, 0, NPCoordinateSpacePlugin, + &screen_x, &screen_y, NPCoordinateSpaceScreen); + double flipped_screen_x, flipped_screen_y; + browser->convertpoint(id(), 0, 0, NPCoordinateSpacePlugin, + &flipped_screen_x, &flipped_screen_y, + NPCoordinateSpaceFlippedScreen); + double window_x, window_y; + browser->convertpoint(id(), 0, 0, NPCoordinateSpacePlugin, + &window_x, &window_y, NPCoordinateSpaceWindow); + double flipped_window_x, flipped_window_y; + browser->convertpoint(id(), 0, 0, NPCoordinateSpacePlugin, + &flipped_window_x, &flipped_window_y, + NPCoordinateSpaceFlippedWindow); + + CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID()); + + // Check that all the coordinates are right. The constants below are based on + // the window frame set in the UI test and the content offset in the test + // html. Y-coordinates are not checked exactly so that the test is robust + // against toolbar changes, info and bookmark bar visibility, etc. + const int kWindowHeight = 400; + const int kWindowXOrigin = 50; + const int kWindowYOrigin = 50; + const int kPluginXContentOffset = 50; + const int kPluginYContentOffset = 50; + const int kChromeYTolerance = 200; + + std::string error_string; + if (screen_x != flipped_screen_x) + error_string = "Flipping screen coordinates shouldn't change x"; + else if (flipped_screen_y != main_display_bounds.size.height - screen_y) + error_string = "Flipped screen coordinates should be flipped vertically"; + else if (screen_x != kWindowXOrigin + kPluginXContentOffset) + error_string = "Screen x location is wrong"; + else if (flipped_screen_y < kWindowYOrigin + kPluginYContentOffset || + flipped_screen_y > kWindowYOrigin + kPluginYContentOffset + + kChromeYTolerance) + error_string = "Screen y location is wrong"; + else if (window_x != flipped_window_x) + error_string = "Flipping window coordinates shouldn't change x"; + else if (flipped_window_y != kWindowHeight - window_y) + error_string = "Flipped window coordinates should be flipped vertically"; + else if (window_x != kPluginXContentOffset) + error_string = "Window x location is wrong"; + else if (flipped_window_y < kPluginYContentOffset || + flipped_window_y > kPluginYContentOffset + kChromeYTolerance) + error_string = "Window y location is wrong"; + + if (!error_string.empty()) { + error_string.append(" - "); + error_string.append(StringForPoint(screen_x, screen_y)); + error_string.append(" - "); + error_string.append(StringForPoint(flipped_screen_x, flipped_screen_y)); + error_string.append(" - "); + error_string.append(StringForPoint(window_x, window_y)); + error_string.append(" - "); + error_string.append(StringForPoint(flipped_window_x, flipped_window_y)); + SetError(error_string); + } +#else + SetError("Unimplemented"); +#endif + SignalTestCompleted(); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_windowless_test.h b/webkit/glue/plugins/test/plugin_windowless_test.h new file mode 100644 index 0000000..f336653 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowless_test.h @@ -0,0 +1,35 @@ +// Copyright (c) 2006-2008 The Chromium Authors. 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_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class contains a list of windowless plugin tests. Please add additional +// tests to this class. +class WindowlessPluginTest : public PluginTest { + public: + // Constructor. + WindowlessPluginTest(NPP id, NPNetscapeFuncs *host_functions); + + // These tests run in windowless plugin mode. + virtual bool IsWindowless() const { return true; } + + // NPAPI HandleEvent handler + virtual int16 HandleEvent(void* event); + + protected: + NPError ExecuteScript(NPNetscapeFuncs* browser, NPP id, + const std::string& script, NPVariant* result); + void ExecuteScriptDeleteInPaint(NPNetscapeFuncs* browser); + void MultipleInstanceSyncCalls(NPNetscapeFuncs* browser); + void ConvertPoint(NPNetscapeFuncs* browser); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H diff --git a/webkit/glue/plugins/test/resource.h b/webkit/glue/plugins/test/resource.h new file mode 100644 index 0000000..c52fa82 --- /dev/null +++ b/webkit/glue/plugins/test/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by npapi_test.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/webkit/glue/plugins/url_request_info_unittest.cc b/webkit/glue/plugins/url_request_info_unittest.cc new file mode 100644 index 0000000..341eeb2 --- /dev/null +++ b/webkit/glue/plugins/url_request_info_unittest.cc @@ -0,0 +1,249 @@ +// 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 "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFrameClient.h" +#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebView.h" + +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/ppb_url_request_info_impl.h" +#include "webkit/plugins/ppapi/ppapi_unittest.h" + +using WebKit::WebCString; +using WebKit::WebFrame; +using WebKit::WebFrameClient; +using WebKit::WebString; +using WebKit::WebView; +using WebKit::WebURL; +using WebKit::WebURLRequest; + +namespace { + +bool IsExpected(const WebCString& web_string, const char* expected) { + const char* result = web_string.data(); + return strcmp(result, expected) == 0; +} + +bool IsExpected(const WebString& web_string, const char* expected) { + return IsExpected(web_string.utf8(), expected); +} + +bool IsNullOrEmpty(const WebString& web_string) { + return web_string.isNull() || web_string.isEmpty(); +} + +// The base class destructor is protected, so derive. +class TestWebFrameClient : public WebFrameClient { +}; + +} // namespace + +namespace webkit { +namespace ppapi { + +class URLRequestInfoTest : public PpapiUnittest { + public: + URLRequestInfoTest() : info_(new PPB_URLRequestInfo_Impl(module())) { + } + + static void SetUpTestCase() { + web_view_ = WebView::create(0, 0); + web_view_->initializeMainFrame(&web_frame_client_); + WebURL web_url(GURL("")); + WebURLRequest url_request; + url_request.initialize(); + url_request.setURL(web_url); + frame_ = web_view_->mainFrame(); + frame_->loadRequest(url_request); + } + + static void TearDownTestCase() { + web_view_->close(); + } + + bool GetDownloadToFile() { + WebURLRequest web_request = info_->ToWebURLRequest(frame_); + return web_request.downloadToFile(); + } + + WebCString GetURL() { + WebURLRequest web_request = info_->ToWebURLRequest(frame_); + return web_request.url().spec(); + } + + WebString GetMethod() { + WebURLRequest web_request = info_->ToWebURLRequest(frame_); + return web_request.httpMethod(); + } + + WebString GetHeaderValue(const char* field) { + WebURLRequest web_request = info_->ToWebURLRequest(frame_); + return web_request.httpHeaderField(WebString::fromUTF8(field)); + } + + scoped_refptr info_; + + static TestWebFrameClient web_frame_client_; + static WebView* web_view_; + static WebFrame* frame_; +}; + +TestWebFrameClient URLRequestInfoTest::web_frame_client_; +WebView* URLRequestInfoTest::web_view_; +WebFrame* URLRequestInfoTest::frame_; + +TEST_F(URLRequestInfoTest, GetInterface) { + const PPB_URLRequestInfo* interface = info_->GetInterface(); + ASSERT_TRUE(interface); + ASSERT_TRUE(interface->Create); + ASSERT_TRUE(interface->IsURLRequestInfo); + ASSERT_TRUE(interface->SetProperty); + ASSERT_TRUE(interface->AppendDataToBody); + ASSERT_TRUE(interface->AppendFileToBody); + ASSERT_TRUE(interface->Create); + ASSERT_TRUE(interface->Create); +} + +TEST_F(URLRequestInfoTest, AsURLRequestInfo) { + ASSERT_EQ(info_, info_->AsPPB_URLRequestInfo_Impl()); +} + +TEST_F(URLRequestInfoTest, StreamToFile) { + info_->SetStringProperty(PP_URLREQUESTPROPERTY_URL, "http://www.google.com"); + + ASSERT_FALSE(GetDownloadToFile()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_STREAMTOFILE, true)); + ASSERT_TRUE(GetDownloadToFile()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_STREAMTOFILE, false)); + ASSERT_FALSE(GetDownloadToFile()); +} + +TEST_F(URLRequestInfoTest, FollowRedirects) { + ASSERT_TRUE(info_->follow_redirects()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS, false)); + ASSERT_FALSE(info_->follow_redirects()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS, true)); + ASSERT_TRUE(info_->follow_redirects()); +} + +TEST_F(URLRequestInfoTest, RecordDownloadProgress) { + ASSERT_FALSE(info_->record_download_progress()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, true)); + ASSERT_TRUE(info_->record_download_progress()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, false)); + ASSERT_FALSE(info_->record_download_progress()); +} + +TEST_F(URLRequestInfoTest, RecordUploadProgress) { + ASSERT_FALSE(info_->record_upload_progress()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS, true)); + ASSERT_TRUE(info_->record_upload_progress()); + + ASSERT_TRUE(info_->SetBooleanProperty( + PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS, false)); + ASSERT_FALSE(info_->record_upload_progress()); +} + +TEST_F(URLRequestInfoTest, SetURL) { + // Test default URL is "about:blank". + ASSERT_TRUE(IsExpected(GetURL(), "about:blank")); + + const char* url = "http://www.google.com/"; + ASSERT_TRUE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_URL, url)); + ASSERT_TRUE(IsExpected(GetURL(), url)); +} + +TEST_F(URLRequestInfoTest, SetMethod) { + // Test default method is "GET". + ASSERT_TRUE(IsExpected(GetMethod(), "GET")); + ASSERT_TRUE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_METHOD, "POST")); + ASSERT_TRUE(IsExpected(GetMethod(), "POST")); +} + +TEST_F(URLRequestInfoTest, SetValidHeaders) { + // Test default header field. + ASSERT_TRUE(IsExpected( + GetHeaderValue("foo"), "")); + // Test that we can set a header field. + ASSERT_TRUE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_HEADERS, "foo: bar")); + ASSERT_TRUE(IsExpected( + GetHeaderValue("foo"), "bar")); + // Test that we can set multiple header fields using \n delimiter. + ASSERT_TRUE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_HEADERS, "foo: bar\nbar: baz")); + ASSERT_TRUE(IsExpected( + GetHeaderValue("foo"), "bar")); + ASSERT_TRUE(IsExpected( + GetHeaderValue("bar"), "baz")); +} + +TEST_F(URLRequestInfoTest, SetInvalidHeaders) { + const char* const kForbiddenHeaderFields[] = { + "accept-charset", + "accept-encoding", + "connection", + "content-length", + "cookie", + "cookie2", + "content-transfer-encoding", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "user-agent", + "via", + + "proxy-foo", // Test for any header starting with proxy- or sec-. + "sec-foo", + }; + + // Test that no forbidden header fields can be set. + for (size_t i = 0; i < arraysize(kForbiddenHeaderFields); ++i) { + std::string headers(kForbiddenHeaderFields[i]); + headers.append(": foo"); + ASSERT_FALSE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_HEADERS, headers.c_str())); + ASSERT_TRUE(IsNullOrEmpty(GetHeaderValue(kForbiddenHeaderFields[i]))); + } + + // Test that forbidden header can't be set in various ways. + ASSERT_FALSE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_HEADERS, "cookie : foo")); + ASSERT_TRUE(IsNullOrEmpty(GetHeaderValue("cookie"))); + + // Test that forbidden header can't be set with an allowed one. + ASSERT_FALSE(info_->SetStringProperty( + PP_URLREQUESTPROPERTY_HEADERS, "foo: bar\ncookie: foo")); + ASSERT_TRUE(IsNullOrEmpty(GetHeaderValue("cookie"))); +} + +// TODO(bbudge) Unit tests for AppendDataToBody, AppendFileToBody. + +} // namespace ppapi +} // namespace webkit + diff --git a/webkit/glue/plugins/webplugin.cc b/webkit/glue/plugins/webplugin.cc new file mode 100644 index 0000000..f780e18f --- /dev/null +++ b/webkit/glue/plugins/webplugin.cc @@ -0,0 +1,31 @@ +// 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 "webkit/glue/plugins/webplugin.h" + +namespace webkit_glue { + +WebPluginGeometry::WebPluginGeometry() + : window(gfx::kNullPluginWindow), + rects_valid(false), + visible(false) { +} + +WebPluginGeometry::~WebPluginGeometry() { +} + +bool WebPluginGeometry::Equals(const WebPluginGeometry& rhs) const { + return window == rhs.window && + window_rect == rhs.window_rect && + clip_rect == rhs.clip_rect && + cutout_rects == rhs.cutout_rects && + rects_valid == rhs.rects_valid && + visible == rhs.visible; +} + +WebPluginDelegate* WebPlugin::delegate() { + return NULL; +} + +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin.h b/webkit/glue/plugins/webplugin.h new file mode 100644 index 0000000..8a61027 --- /dev/null +++ b/webkit/glue/plugins/webplugin.h @@ -0,0 +1,200 @@ +// Copyright (c) 2006-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 WEBKIT_GLUE_WEBPLUGIN_H_ +#define WEBKIT_GLUE_WEBPLUGIN_H_ + +#include +#include + +#include "base/basictypes.h" +#include "gfx/native_widget_types.h" +#include "gfx/rect.h" + +// TODO(port): this typedef is obviously incorrect on non-Windows +// platforms, but now a lot of code now accidentally depends on them +// existing. #ifdef out these declarations and fix all the users. +typedef void* HANDLE; + +class GURL; +struct NPObject; + +namespace WebKit { +class WebFrame; +} + +namespace webkit_glue { + +class WebPluginDelegate; +class WebPluginParentView; +class WebPluginResourceClient; +#if defined(OS_MACOSX) +class WebPluginAcceleratedSurface; +#endif + +// Describes the new location for a plugin window. +struct WebPluginGeometry { + WebPluginGeometry(); + ~WebPluginGeometry(); + + bool Equals(const WebPluginGeometry& rhs) const; + + // On Windows, this is the plugin window in the plugin process. + // On X11, this is the XID of the plugin-side GtkPlug containing the + // GtkSocket hosting the actual plugin window. + // + // On Mac OS X, all of the plugin types are currently "windowless" + // (window == 0) except for the special case of the GPU plugin, + // which currently performs rendering on behalf of the Pepper 3D API + // and WebGL. The GPU plugin uses a simple integer for the + // PluginWindowHandle which is used to map to a side data structure + // containing information about the plugin. Soon this plugin will be + // generalized, at which point this mechanism will be rethought or + // removed. + gfx::PluginWindowHandle window; + gfx::Rect window_rect; + // Clip rect (include) and cutouts (excludes), relative to + // window_rect origin. + gfx::Rect clip_rect; + std::vector cutout_rects; + bool rects_valid; + bool visible; +}; + +// The WebKit side of a plugin implementation. It provides wrappers around +// operations that need to interact with the frame and other WebCore objects. +class WebPlugin { + public: + virtual ~WebPlugin() {} + + // Called by the plugin delegate to let the WebPlugin know if the plugin is + // windowed (i.e. handle is not NULL) or windowless (handle is NULL). This + // tells the WebPlugin to send mouse/keyboard events to the plugin delegate, + // as well as the information about the HDC for paint operations. + virtual void SetWindow(gfx::PluginWindowHandle window) = 0; + + // Whether input events should be sent to the delegate. + virtual void SetAcceptsInputEvents(bool accepts) = 0; + + // Called by the plugin delegate to let it know that the window is being + // destroyed. + virtual void WillDestroyWindow(gfx::PluginWindowHandle window) = 0; +#if defined(OS_WIN) + // The pump_messages_event is a event handle which is valid only for + // windowless plugins and is used in NPP_HandleEvent calls to pump messages + // if the plugin enters a modal loop. + // Cancels a pending request. + virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) = 0; +#endif + virtual void CancelResource(unsigned long id) = 0; + virtual void Invalidate() = 0; + virtual void InvalidateRect(const gfx::Rect& rect) = 0; + + // Returns the NPObject for the browser's window object. + virtual NPObject* GetWindowScriptNPObject() = 0; + + // Returns the DOM element that loaded the plugin. + virtual NPObject* GetPluginElement() = 0; + + // Cookies + virtual void SetCookie(const GURL& url, + const GURL& first_party_for_cookies, + const std::string& cookie) = 0; + virtual std::string GetCookies(const GURL& url, + const GURL& first_party_for_cookies) = 0; + + // Shows a modal HTML dialog containing the given URL. json_arguments are + // passed to the dialog via the DOM 'window.chrome.dialogArguments', and the + // retval is the string returned by 'window.chrome.send("DialogClose", + // retval)'. + virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + std::string* json_retval) = 0; + + // When a default plugin has downloaded the plugin list and finds it is + // available, it calls this method to notify the renderer. Also it will update + // the status when user clicks on the plugin to install. + virtual void OnMissingPluginStatus(int status) = 0; + + // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated + // by plugins. If the plugin wants notification of the result, notify_id will + // be non-zero. + 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) = 0; + + // Cancels document load. + virtual void CancelDocumentLoad() = 0; + + // Initiates a HTTP range request for an existing stream. + virtual void InitiateHTTPRangeRequest(const char* url, + const char* range_info, + int range_request_id) = 0; + + // Returns true iff in off the record (Incognito) mode. + virtual bool IsOffTheRecord() = 0; + + // Called when the WebPluginResourceClient instance is deleted. + virtual void ResourceClientDeleted( + WebPluginResourceClient* resource_client) {} + + // Defers the loading of the resource identified by resource_id. This is + // controlled by the defer parameter. + virtual void SetDeferResourceLoading(unsigned long resource_id, + bool defer) = 0; + +#if defined(OS_MACOSX) + // Enables/disables plugin IME. + virtual void SetImeEnabled(bool enabled) {}; + + // Synthesize a fake window handle for the plug-in to identify the instance + // to the browser, allowing mapping to a surface for hardware accelleration + // of plug-in content. The browser generates the handle which is then set on + // the plug-in. |opaque| indicates whether the content should be treated as + // opaque or translucent. + // TODO(stuartmorgan): Move this into WebPluginProxy. + virtual void BindFakePluginWindowHandle(bool opaque) {} + + // Returns the accelerated surface abstraction for accelerated plugins. + virtual WebPluginAcceleratedSurface* GetAcceleratedSurface() { return NULL; } +#endif + + // Gets the WebPluginDelegate that implements the interface. + // This API is only for use with Pepper, and is only overridden + // by in-renderer implementations. + virtual WebPluginDelegate* delegate(); + + // Handles NPN_URLRedirectResponse calls issued by plugins in response to + // HTTP URL redirect notifications. + virtual void URLRedirectResponse(bool allow, int resource_id) = 0; +}; + +// Simpler version of ResourceHandleClient that lends itself to proxying. +class WebPluginResourceClient { + public: + virtual ~WebPluginResourceClient() {} + virtual void WillSendRequest(const GURL& url, int http_status_code) = 0; + // The request_is_seekable parameter indicates whether byte range requests + // can be issued for the underlying stream. + virtual void DidReceiveResponse(const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified, + bool request_is_seekable) = 0; + virtual void DidReceiveData(const char* buffer, int length, + int data_offset) = 0; + virtual void DidFinishLoading() = 0; + virtual void DidFail() = 0; + virtual bool IsMultiByteResponseExpected() = 0; + virtual int ResourceId() = 0; +}; + +} // namespace webkit_glue + +#endif // #ifndef WEBKIT_GLUE_WEBPLUGIN_H_ diff --git a/webkit/glue/plugins/webplugin_2d_device_delegate.cc b/webkit/glue/plugins/webplugin_2d_device_delegate.cc new file mode 100644 index 0000000..f971e20 --- /dev/null +++ b/webkit/glue/plugins/webplugin_2d_device_delegate.cc @@ -0,0 +1,53 @@ +// 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 "webkit/glue/plugins/webplugin_2d_device_delegate.h" + +namespace webkit_glue { + +NPError WebPlugin2DDeviceDelegate::Device2DQueryCapability(int32 capability, + int32* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DQueryConfig( + const NPDeviceContext2DConfig* request, + NPDeviceContext2DConfig* obtain) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DInitializeContext( + const NPDeviceContext2DConfig* config, + NPDeviceContext2D* context) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DSetStateContext( + NPDeviceContext2D* context, + int32 state, + intptr_t value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DGetStateContext( + NPDeviceContext2D* context, + int32 state, + intptr_t* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DFlushContext( + NPP id, + NPDeviceContext2D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin2DDeviceDelegate::Device2DDestroyContext( + NPDeviceContext2D* context) { + return NPERR_GENERIC_ERROR; +} + +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin_2d_device_delegate.h b/webkit/glue/plugins/webplugin_2d_device_delegate.h new file mode 100644 index 0000000..e18c2fd --- /dev/null +++ b/webkit/glue/plugins/webplugin_2d_device_delegate.h @@ -0,0 +1,43 @@ +// 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 WEBKIT_GLUE_PLUGINS_WEBPLUGIN_2D_DEVICE_DELEGATE_H_ +#define WEBKIT_GLUE_PLUGINS_WEBPLUGIN_2D_DEVICE_DELEGATE_H_ + +#include "base/basictypes.h" +#include "third_party/npapi/bindings/npapi_extensions.h" + +namespace webkit_glue { + +// Interface for the NPAPI 2D device extension. This class implements "NOP" +// versions of all these functions so it can be used seamlessly by the +// "regular" plugin delegate while being overridden by the "pepper" one. +class WebPlugin2DDeviceDelegate { + public: + virtual NPError Device2DQueryCapability(int32 capability, int32* value); + virtual NPError Device2DQueryConfig(const NPDeviceContext2DConfig* request, + NPDeviceContext2DConfig* obtain); + virtual NPError Device2DInitializeContext( + const NPDeviceContext2DConfig* config, + NPDeviceContext2D* context); + virtual NPError Device2DSetStateContext(NPDeviceContext2D* context, + int32 state, + intptr_t value); + virtual NPError Device2DGetStateContext(NPDeviceContext2D* context, + int32 state, + intptr_t* value); + virtual NPError Device2DFlushContext(NPP id, + NPDeviceContext2D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data); + virtual NPError Device2DDestroyContext(NPDeviceContext2D* context); + + protected: + WebPlugin2DDeviceDelegate() {} + virtual ~WebPlugin2DDeviceDelegate() {} +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_PLUGINS_WEBPLUGIN_2D_DEVICE_DELEGATE_H_ diff --git a/webkit/glue/plugins/webplugin_3d_device_delegate.cc b/webkit/glue/plugins/webplugin_3d_device_delegate.cc new file mode 100644 index 0000000..93dffa6 --- /dev/null +++ b/webkit/glue/plugins/webplugin_3d_device_delegate.cc @@ -0,0 +1,110 @@ +// 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 "webkit/glue/plugins/webplugin_3d_device_delegate.h" + +namespace webkit_glue { + +NPError WebPlugin3DDeviceDelegate::Device3DQueryCapability(int32 capability, + int32* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DQueryConfig( + const NPDeviceContext3DConfig* request, + NPDeviceContext3DConfig* obtain) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DInitializeContext( + const NPDeviceContext3DConfig* config, + NPDeviceContext3D* context) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DSetStateContext( + NPDeviceContext3D* context, + int32 state, + intptr_t value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DGetStateContext( + NPDeviceContext3D* context, + int32 state, + intptr_t* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DFlushContext( + NPP id, + NPDeviceContext3D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DDestroyContext( + NPDeviceContext3D* context) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DCreateBuffer(NPDeviceContext3D* context, + size_t size, + int32* id) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DDestroyBuffer( + NPDeviceContext3D* context, + int32 id) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DMapBuffer(NPDeviceContext3D* context, + int32 id, + NPDeviceBuffer* buffer) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DGetNumConfigs(int32* num_configs) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DGetConfigAttribs( + int32 config, + int32* attrib_list) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DCreateContext( + int32 config, + const int32* attrib_list, + NPDeviceContext3D** context) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DRegisterCallback( + NPP id, + NPDeviceContext* context, + int32 callback_type, + NPDeviceGenericCallbackPtr callback, + void* callback_data) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPlugin3DDeviceDelegate::Device3DSynchronizeContext( + NPP id, + NPDeviceContext3D* context, + NPDeviceSynchronizationMode mode, + const int32* input_attrib_list, + int32* output_attrib_list, + NPDeviceSynchronizeContextCallbackPtr callback, + void* callback_data) { + return NPERR_GENERIC_ERROR; +} + + +} // namespace webkit_glue + diff --git a/webkit/glue/plugins/webplugin_3d_device_delegate.h b/webkit/glue/plugins/webplugin_3d_device_delegate.h new file mode 100644 index 0000000..2f64b45 --- /dev/null +++ b/webkit/glue/plugins/webplugin_3d_device_delegate.h @@ -0,0 +1,71 @@ +// 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 WEBKIT_GLUE_PLUGINS_WEBPLUGIN_3D_DEVICE_DELEGATE_H_ +#define WEBKIT_GLUE_PLUGINS_WEBPLUGIN_3D_DEVICE_DELEGATE_H_ + +#include "base/basictypes.h" +#include "third_party/npapi/bindings/npapi_extensions.h" + +namespace webkit_glue { + +// Interface for the NPAPI 3D device extension. This class implements "NOP" +// versions of all these functions so it can be used seamlessly by the +// "regular" plugin delegate while being overridden by the "pepper" one. +class WebPlugin3DDeviceDelegate { + public: + virtual NPError Device3DQueryCapability(int32 capability, int32* value); + virtual NPError Device3DQueryConfig(const NPDeviceContext3DConfig* request, + NPDeviceContext3DConfig* obtain); + virtual NPError Device3DInitializeContext( + const NPDeviceContext3DConfig* config, + NPDeviceContext3D* context); + virtual NPError Device3DSetStateContext(NPDeviceContext3D* context, + int32 state, + intptr_t value); + virtual NPError Device3DGetStateContext(NPDeviceContext3D* context, + int32 state, + intptr_t* value); + virtual NPError Device3DFlushContext(NPP id, + NPDeviceContext3D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data); + virtual NPError Device3DDestroyContext(NPDeviceContext3D* context); + virtual NPError Device3DCreateBuffer(NPDeviceContext3D* context, + size_t size, + int32* id); + virtual NPError Device3DDestroyBuffer(NPDeviceContext3D* context, + int32 id); + virtual NPError Device3DMapBuffer(NPDeviceContext3D* context, + int32 id, + NPDeviceBuffer* buffer); + virtual NPError Device3DGetNumConfigs(int32* num_configs); + virtual NPError Device3DGetConfigAttribs(int32 config, + int32* attrib_list); + virtual NPError Device3DCreateContext(int32 config, + const int32* attrib_list, + NPDeviceContext3D** context); + virtual NPError Device3DRegisterCallback( + NPP id, + NPDeviceContext* context, + int32 callback_type, + NPDeviceGenericCallbackPtr callback, + void* callback_data); + virtual NPError Device3DSynchronizeContext( + NPP id, + NPDeviceContext3D* context, + NPDeviceSynchronizationMode mode, + const int32* input_attrib_list, + int32* output_attrib_list, + NPDeviceSynchronizeContextCallbackPtr callback, + void* callback_data); + + protected: + WebPlugin3DDeviceDelegate() {} + virtual ~WebPlugin3DDeviceDelegate() {} +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_PLUGINS_WEBPLUGIN_3D_DEVICE_DELEGATE_H_ diff --git a/webkit/glue/plugins/webplugin_accelerated_surface_mac.h b/webkit/glue/plugins/webplugin_accelerated_surface_mac.h new file mode 100644 index 0000000..13980ca --- /dev/null +++ b/webkit/glue/plugins/webplugin_accelerated_surface_mac.h @@ -0,0 +1,44 @@ +// Copyright (c) 2006-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 WEBKIT_GLUE_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_ +#define WEBKIT_GLUE_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_ +#pragma once + +#include "gfx/native_widget_types.h" +#include "gfx/size.h" + +// Avoid having to include OpenGL headers here. +typedef struct _CGLContextObject* CGLContextObj; + +namespace webkit_glue { + +// Interface class for interacting with an accelerated plugin surface, used +// for the Core Animation flavors of plugin drawing on the Mac. +class WebPluginAcceleratedSurface { + public: + virtual ~WebPluginAcceleratedSurface() {} + + // Sets the window handle used throughout the browser to identify this + // surface. + virtual void SetWindowHandle(gfx::PluginWindowHandle window) = 0; + + // Sets the size of the surface. + virtual void SetSize(const gfx::Size& size) = 0; + + // Returns the context used to draw into this surface. + // If initializing the surface failed, this will be NULL. + virtual CGLContextObj context() = 0; + + // Readies the surface for drawing. Must be called before any drawing session. + virtual void StartDrawing() = 0; + + // Ends a drawing session. Changes to the surface may not be reflected until + // this is called. + virtual void EndDrawing() = 0; +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_ diff --git a/webkit/glue/plugins/webplugin_audio_device_delegate.cc b/webkit/glue/plugins/webplugin_audio_device_delegate.cc new file mode 100644 index 0000000..8cc3d62 --- /dev/null +++ b/webkit/glue/plugins/webplugin_audio_device_delegate.cc @@ -0,0 +1,50 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/webplugin_audio_device_delegate.h" + +namespace webkit_glue { + +NPError WebPluginAudioDeviceDelegate::DeviceAudioQueryCapability( + int32 capability, int32* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioQueryConfig( + const NPDeviceContextAudioConfig* request, + NPDeviceContextAudioConfig* obtain) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioInitializeContext( + const NPDeviceContextAudioConfig* config, + NPDeviceContextAudio* context) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioSetStateContext( + NPDeviceContextAudio* context, + int32 state, intptr_t value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioGetStateContext( + NPDeviceContextAudio* context, + int32 state, intptr_t* value) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioFlushContext( + NPP id, NPDeviceContextAudio* context, + NPDeviceFlushContextCallbackPtr callback, void* user_data) { + return NPERR_GENERIC_ERROR; +} + +NPError WebPluginAudioDeviceDelegate::DeviceAudioDestroyContext( + NPDeviceContextAudio* context) { + return NPERR_GENERIC_ERROR; +} + + +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin_audio_device_delegate.h b/webkit/glue/plugins/webplugin_audio_device_delegate.h new file mode 100644 index 0000000..de85433 --- /dev/null +++ b/webkit/glue/plugins/webplugin_audio_device_delegate.h @@ -0,0 +1,42 @@ +// 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 WEBKIT_GLUE_PLUGINS_WEBPLUGIN_AUDIO_DEVICE_DELEGATE_H_ +#define WEBKIT_GLUE_PLUGINS_WEBPLUGIN_AUDIO_DEVICE_DELEGATE_H_ + +#include "base/basictypes.h" +#include "third_party/npapi/bindings/npapi_extensions.h" + +namespace webkit_glue { + +// Interface for the NPAPI audio device extension. This class implements "NOP" +// versions of all these functions so it can be used seamlessly by the +// "regular" plugin delegate while being overridden by the "pepper" one. +class WebPluginAudioDeviceDelegate { + public: + virtual NPError DeviceAudioQueryCapability(int32 capability, int32* value); + virtual NPError DeviceAudioQueryConfig( + const NPDeviceContextAudioConfig* request, + NPDeviceContextAudioConfig* obtain); + virtual NPError DeviceAudioInitializeContext( + const NPDeviceContextAudioConfig* config, + NPDeviceContextAudio* context); + virtual NPError DeviceAudioSetStateContext(NPDeviceContextAudio* context, + int32 state, intptr_t value); + virtual NPError DeviceAudioGetStateContext(NPDeviceContextAudio* context, + int32 state, intptr_t* value); + virtual NPError DeviceAudioFlushContext( + NPP id, NPDeviceContextAudio* context, + NPDeviceFlushContextCallbackPtr callback, void* user_data); + virtual NPError DeviceAudioDestroyContext(NPDeviceContextAudio* context); + + protected: + WebPluginAudioDeviceDelegate() {} + virtual ~WebPluginAudioDeviceDelegate() {} +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_PLUGINS_WEBPLUGIN_AUDIO_DEVICE_DELEGATE_H_ + diff --git a/webkit/glue/plugins/webplugin_delegate.cc b/webkit/glue/plugins/webplugin_delegate.cc new file mode 100644 index 0000000..c3fb53b --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate.cc @@ -0,0 +1,40 @@ +// 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 "webkit/glue/plugins/webplugin_delegate.h" + +namespace webkit_glue { + +bool WebPluginDelegate::StartFind(const string16& search_text, + bool case_sensitive, + int identifier) { + return false; +} + +NPWidgetExtensions* WebPluginDelegate::GetWidgetExtensions() { + return NULL; +} + +bool WebPluginDelegate::SetCursor(NPCursorType type) { + return false; +} + +NPFontExtensions* WebPluginDelegate::GetFontExtensions() { + return NULL; +} + +bool WebPluginDelegate::HasSelection() const { + return false; +} + +string16 WebPluginDelegate::GetSelectionAsText() const { + return string16(); +} + +string16 WebPluginDelegate::GetSelectionAsMarkup() const { + return string16(); +} + + +} // namespace webkit_glue diff --git a/webkit/glue/plugins/webplugin_delegate.h b/webkit/glue/plugins/webplugin_delegate.h new file mode 100644 index 0000000..ac7bb5c --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate.h @@ -0,0 +1,166 @@ +// 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 WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ +#define WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ + +#include +#include + +#include "base/string16.h" +#include "build/build_config.h" +#include "gfx/native_widget_types.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npapi_extensions.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" +#include "webkit/glue/plugins/webplugin_2d_device_delegate.h" +#include "webkit/glue/plugins/webplugin_3d_device_delegate.h" +#include "webkit/glue/plugins/webplugin_audio_device_delegate.h" +#include "webkit/glue/plugins/webplugin_file_delegate.h" +#include "webkit/glue/plugins/webplugin_print_delegate.h" + +class FilePath; +class GURL; +struct NPObject; + +namespace WebKit { +class WebInputEvent; +struct WebCursorInfo; +} + +namespace gfx { +class Rect; +} + +namespace webkit_glue { + +class WebPlugin; +class WebPluginResourceClient; + +// This is the interface that a plugin implementation needs to provide. +class WebPluginDelegate : public WebPlugin2DDeviceDelegate, + public WebPlugin3DDeviceDelegate, + public WebPluginAudioDeviceDelegate, + public WebPluginPrintDelegate, + public WebPluginFileDelegate { + public: + virtual ~WebPluginDelegate() {} + + // Initializes the plugin implementation with the given (UTF8) arguments. + // Note that the lifetime of WebPlugin must be longer than this delegate. + // If this function returns false the plugin isn't started and shouldn't be + // called again. If this method succeeds, then the WebPlugin is valid until + // PluginDestroyed is called. + // The load_manually parameter if true indicates that the plugin data would + // be passed from webkit. if false indicates that the plugin should download + // the data. This also controls whether the plugin is instantiated as a full + // page plugin (NP_FULL) or embedded (NP_EMBED). + virtual bool Initialize(const GURL& url, + const std::vector& arg_names, + const std::vector& arg_values, + WebPlugin* plugin, + bool load_manually) = 0; + + // Called when the WebPlugin is being destroyed. This is a signal to the + // delegate that it should tear-down the plugin implementation and not call + // methods on the WebPlugin again. + virtual void PluginDestroyed() = 0; + + // Update the geometry of the plugin. This is a request to move the + // plugin, relative to its containing window, to the coords given by + // window_rect. Its contents should be clipped to the coords given + // by clip_rect, which are relative to the origin of the plugin + // window. The clip_rect is in plugin-relative coordinates. + virtual void UpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) = 0; + + // Tells the plugin to paint the damaged rect. |canvas| is only used for + // windowless plugins. + virtual void Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect) = 0; + + // Tells the plugin to print itself. + virtual void Print(gfx::NativeDrawingContext hdc) = 0; + + // Informs the plugin that it has gained or lost focus. This is only called in + // windowless mode. + virtual void SetFocus(bool focused) = 0; + + // For windowless plugins, gives them a user event like mouse/keyboard. + // Returns whether the event was handled. This is only called in windowsless + // mode. See NPAPI NPP_HandleEvent for more information. + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebKit::WebCursorInfo* cursor) = 0; + + // Gets the NPObject associated with the plugin for scripting. + virtual NPObject* GetPluginScriptableObject() = 0; + + // Receives notification about a resource load that the plugin initiated + // for a frame. + virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason, + int notify_id) = 0; + + // Returns the process id of the process that is running the plugin. + virtual int GetProcessId() = 0; + + // The result, UTF-8 encoded, of the script execution is returned via this + // function. + virtual void SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id) = 0; + + // Receives notification about data being available. + virtual void DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified) = 0; + + // Receives the data. + virtual void DidReceiveManualData(const char* buffer, int length) = 0; + + // Indicates end of data load. + virtual void DidFinishManualLoading() = 0; + + // Indicates a failure in data receipt. + virtual void DidManualLoadFail() = 0; + + // Only supported when the plugin is the default plugin. + virtual void InstallMissingPlugin() = 0; + + // Creates a WebPluginResourceClient instance and returns the same. + virtual WebPluginResourceClient* CreateResourceClient( + unsigned long resource_id, + const GURL& url, + int notify_id) = 0; + + // Creates a WebPluginResourceClient instance for an existing stream that is + // has become seekable. + virtual WebPluginResourceClient* CreateSeekableResourceClient( + unsigned long resource_id, int range_request_id) = 0; + + // See WebPluginContainerImpl's description of the interface. + virtual bool StartFind(const string16& search_text, + bool case_sensitive, + int identifier); + virtual void SelectFindResult(bool forward) {} + virtual void StopFind() {} + virtual void NumberOfFindResultsChanged(int total, bool final_result) {} + virtual void SelectedFindResultChanged(int index) {} + virtual NPWidgetExtensions* GetWidgetExtensions(); + virtual bool SetCursor(NPCursorType type); + virtual NPFontExtensions* GetFontExtensions(); + + // Used for zooming of full page plugins. 0 means reset, while -1 means zoom + // out and +1 means zoom in. + virtual void SetZoomFactor(float scale, bool text_only) {} + // Gets the selected text, if any. + virtual bool HasSelection() const; + virtual string16 GetSelectionAsText() const; + virtual string16 GetSelectionAsMarkup() const; +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H_ diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc new file mode 100644 index 0000000..e3e4f9d --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -0,0 +1,304 @@ +// 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 "webkit/glue/plugins/webplugin_delegate_impl.h" + +#include +#include + +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/process_util.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/webkit_glue.h" + +using webkit_glue::WebPlugin; +using webkit_glue::WebPluginDelegate; +using webkit_glue::WebPluginResourceClient; +using WebKit::WebCursorInfo; +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; + +WebPluginDelegateImpl* WebPluginDelegateImpl::Create( + const FilePath& filename, + const std::string& mime_type, + gfx::PluginWindowHandle containing_view) { + scoped_refptr plugin_lib( + NPAPI::PluginLib::CreatePluginLib(filename)); + if (plugin_lib.get() == NULL) + return NULL; + + NPError err = plugin_lib->NP_Initialize(); + if (err != NPERR_NO_ERROR) + return NULL; + + scoped_refptr instance( + plugin_lib->CreateInstance(mime_type)); + return new WebPluginDelegateImpl(containing_view, instance.get()); +} + +void WebPluginDelegateImpl::PluginDestroyed() { + if (handle_event_depth_) { + MessageLoop::current()->DeleteSoon(FROM_HERE, this); + } else { + delete this; + } +} + +bool WebPluginDelegateImpl::Initialize( + const GURL& url, + const std::vector& arg_names, + const std::vector& arg_values, + WebPlugin* plugin, + bool load_manually) { + plugin_ = plugin; + + instance_->set_web_plugin(plugin_); + if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) { + NPAPI::PluginLib* plugin_lib = instance()->plugin_lib(); + if (plugin_lib->instance_count() > 1) { + return false; + } + } + + if (quirks_ & PLUGIN_QUIRK_DIE_AFTER_UNLOAD) + webkit_glue::SetForcefullyTerminatePluginProcess(true); + + int argc = 0; + scoped_array argn(new char*[arg_names.size()]); + scoped_array argv(new char*[arg_names.size()]); + for (size_t i = 0; i < arg_names.size(); ++i) { + if (quirks_ & PLUGIN_QUIRK_NO_WINDOWLESS && + LowerCaseEqualsASCII(arg_names[i], "windowlessvideo")) { + continue; + } + argn[argc] = const_cast(arg_names[i].c_str()); + argv[argc] = const_cast(arg_values[i].c_str()); + argc++; + } + + creation_succeeded_ = instance_->Start( + url, argn.get(), argv.get(), argc, load_manually); + if (!creation_succeeded_) + return false; + + windowless_ = instance_->windowless(); + if (!windowless_) { + if (!WindowedCreatePlugin()) + return false; + } else { + // For windowless plugins we should set the containing window handle + // as the instance window handle. This is what Safari does. Not having + // a valid window handle causes subtle bugs with plugins which retrieve + // the window handle and validate the same. The window handle can be + // retrieved via NPN_GetValue of NPNVnetscapeWindow. + instance_->set_window_handle(parent_); + } + + bool should_load = PlatformInitialize(); + + plugin_url_ = url.spec(); + + return should_load; +} + +void WebPluginDelegateImpl::DestroyInstance() { + if (instance_ && (instance_->npp()->ndata != NULL)) { + // Shutdown all streams before destroying so that + // no streams are left "in progress". Need to do + // this before calling set_web_plugin(NULL) because the + // instance uses the helper to do the download. + instance_->CloseStreams(); + + window_.window = NULL; + if (creation_succeeded_ && + !(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { + instance_->NPP_SetWindow(&window_); + } + + instance_->NPP_Destroy(); + + instance_->set_web_plugin(NULL); + + PlatformDestroyInstance(); + + instance_ = 0; + } +} + +void WebPluginDelegateImpl::UpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + + if (first_set_window_call_) { + first_set_window_call_ = false; + // Plugins like media player on Windows have a bug where in they handle the + // first geometry update and ignore the rest resulting in painting issues. + // This quirk basically ignores the first set window call sequence for + // these plugins and has been tested for Windows plugins only. + if (quirks_ & PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL) + return; + } + + if (windowless_) { + WindowlessUpdateGeometry(window_rect, clip_rect); + } else { + WindowedUpdateGeometry(window_rect, clip_rect); + } +} + +void WebPluginDelegateImpl::SetFocus(bool focused) { + DCHECK(windowless_); + // This is called when internal WebKit focus (the focused element on the page) + // changes, but plugins need to know about OS-level focus, so we have an extra + // layer of focus tracking. + // + // On Windows, historically browsers did not set focus events to windowless + // plugins when the toplevel window focus changes. Sending such focus events + // breaks full screen mode in Flash because it will come out of full screen + // mode when it loses focus, and its full screen window causes the browser to + // lose focus. + has_webkit_focus_ = focused; +#ifndef OS_WIN + if (containing_view_has_focus_) + SetPluginHasFocus(focused); +#else + SetPluginHasFocus(focused); +#endif +} + +void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) { + if (focused == plugin_has_focus_) + return; + if (PlatformSetPluginHasFocus(focused)) + plugin_has_focus_ = focused; +} + +void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) { + containing_view_has_focus_ = has_focus; + if (!windowless_) + return; +#ifndef OS_WIN // See SetFocus above. + SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_); +#endif +} + +NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() { + return instance_->GetPluginScriptableObject(); +} + +void WebPluginDelegateImpl::DidFinishLoadWithReason(const GURL& url, + NPReason reason, + int notify_id) { + if (quirks_ & PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS && + reason == NPRES_NETWORK_ERR) { + // Flash needs this or otherwise it unloads the launching swf object. + reason = NPRES_DONE; + } + + instance()->DidFinishLoadWithReason(url, reason, notify_id); +} + +int WebPluginDelegateImpl::GetProcessId() { + // We are in process, so the plugin pid is this current process pid. + return base::GetCurrentProcId(); +} + +void WebPluginDelegateImpl::SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id) { + instance()->SendJavaScriptStream(url, result, success, notify_id); +} + +void WebPluginDelegateImpl::DidReceiveManualResponse( + const GURL& url, const std::string& mime_type, + const std::string& headers, uint32 expected_length, uint32 last_modified) { + if (!windowless_) { + // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in + // Flash. See http://b/issue?id=892174. + DCHECK(windowed_did_set_window_); + } + + instance()->DidReceiveManualResponse(url, mime_type, headers, + expected_length, last_modified); +} + +void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer, + int length) { + instance()->DidReceiveManualData(buffer, length); +} + +void WebPluginDelegateImpl::DidFinishManualLoading() { + instance()->DidFinishManualLoading(); +} + +void WebPluginDelegateImpl::DidManualLoadFail() { + instance()->DidManualLoadFail(); +} + +FilePath WebPluginDelegateImpl::GetPluginPath() { + return instance()->plugin_lib()->plugin_info().path; +} + +void WebPluginDelegateImpl::WindowedUpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + if (WindowedReposition(window_rect, clip_rect) || + !windowed_did_set_window_) { + // Let the plugin know that it has been moved + WindowedSetWindow(); + } +} + +bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, + WebCursorInfo* cursor_info) { + DCHECK(windowless_) << "events should only be received in windowless mode"; + + bool pop_user_gesture = false; + if (IsUserGesture(event)) { + pop_user_gesture = true; + instance()->PushPopupsEnabledState(true); + } + + bool handled = PlatformHandleInputEvent(event, cursor_info); + + if (pop_user_gesture) { + instance()->PopPopupsEnabledState(); + } + + return handled; +} + +bool WebPluginDelegateImpl::IsUserGesture(const WebInputEvent& event) { + switch (event.type) { + case WebInputEvent::MouseDown: + case WebInputEvent::MouseUp: + case WebInputEvent::KeyDown: + case WebInputEvent::KeyUp: + return true; + default: + return false; + } + return false; +} + +WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( + unsigned long resource_id, const GURL& url, int notify_id) { + return instance()->CreateStream( + resource_id, url, std::string(), notify_id); +} + +WebPluginResourceClient* WebPluginDelegateImpl::CreateSeekableResourceClient( + unsigned long resource_id, int range_request_id) { + return instance()->GetRangeRequest(range_request_id); +} diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h new file mode 100644 index 0000000..4046c95 --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -0,0 +1,511 @@ +// 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 WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ +#define WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ + +#include "build/build_config.h" + +#include +#include + +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "base/task.h" +#include "base/time.h" +#include "base/timer.h" +#include "gfx/native_widget_types.h" +#include "gfx/rect.h" +#include "third_party/npapi/bindings/npapi.h" +#include "webkit/glue/plugins/webplugin_delegate.h" +#include "webkit/glue/webcursor.h" + +#if defined(USE_X11) +#include "app/x11_util.h" + +typedef struct _GdkDrawable GdkPixmap; +#endif + +class FilePath; + +namespace NPAPI { +class PluginInstance; +} + +namespace WebKit { +class WebMouseEvent; +} + +#if defined(OS_MACOSX) +class ExternalDragTracker; +#ifndef NP_NO_QUICKDRAW +class QuickDrawDrawingManager; +#endif +#ifdef __OBJC__ +@class CALayer; +@class CARenderer; +#else +class CALayer; +class CARenderer; +#endif +namespace webkit_glue { +class WebPluginAcceleratedSurface; +} +#endif + +// An implementation of WebPluginDelegate that runs in the plugin process, +// proxied from the renderer by WebPluginDelegateProxy. +class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { + public: + enum PluginQuirks { + PLUGIN_QUIRK_SETWINDOW_TWICE = 1, // Win32 + PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE = 2, // Win32 + PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY = 4, // Win32 + PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY = 8, // Win32 + PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES = 16, // Win32 + PLUGIN_QUIRK_DIE_AFTER_UNLOAD = 32, // Win32 + PLUGIN_QUIRK_PATCH_SETCURSOR = 64, // Win32 + PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS = 128, // Win32 + PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW = 256, // Linux + PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW = 512, // Linux + PLUGIN_QUIRK_NO_WINDOWLESS = 1024, // Windows + PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 2048, // Windows + PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS = 4096, // Windows + PLUGIN_QUIRK_ALLOW_FASTER_QUICKDRAW_PATH = 8192, // Mac + PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE = 16384, // Windows + PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux + PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows. + }; + + static WebPluginDelegateImpl* Create(const FilePath& filename, + const std::string& mime_type, + gfx::PluginWindowHandle containing_view); + + static bool IsPluginDelegateWindow(gfx::NativeWindow window); + static bool GetPluginNameFromWindow(gfx::NativeWindow window, + std::wstring *plugin_name); + + // Returns true if the window handle passed in is that of the dummy + // activation window for windowless plugins. + static bool IsDummyActivationWindow(gfx::NativeWindow window); + + // WebPluginDelegate implementation + virtual bool Initialize(const GURL& url, + const std::vector& arg_names, + const std::vector& arg_values, + webkit_glue::WebPlugin* plugin, + bool load_manually); + virtual void PluginDestroyed(); + virtual void UpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + virtual void Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect); + virtual void Print(gfx::NativeDrawingContext context); + virtual void SetFocus(bool focused); + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebKit::WebCursorInfo* cursor_info); + virtual NPObject* GetPluginScriptableObject(); + virtual void DidFinishLoadWithReason( + const GURL& url, NPReason reason, int notify_id); + virtual int GetProcessId(); + virtual void SendJavaScriptStream(const GURL& url, + const std::string& result, + bool success, + int notify_id); + virtual void DidReceiveManualResponse(const GURL& url, + const std::string& mime_type, + const std::string& headers, + uint32 expected_length, + uint32 last_modified); + virtual void DidReceiveManualData(const char* buffer, int length); + virtual void DidFinishManualLoading(); + virtual void DidManualLoadFail(); + virtual void InstallMissingPlugin(); + virtual webkit_glue::WebPluginResourceClient* CreateResourceClient( + unsigned long resource_id, const GURL& url, int notify_id); + virtual webkit_glue::WebPluginResourceClient* CreateSeekableResourceClient( + unsigned long resource_id, int range_request_id); + // End of WebPluginDelegate implementation. + + bool IsWindowless() const { return windowless_ ; } + gfx::Rect GetRect() const { return window_rect_; } + gfx::Rect GetClipRect() const { return clip_rect_; } + + // Returns the path for the library implementing this plugin. + FilePath GetPluginPath(); + + // Returns a combination of PluginQuirks. + int GetQuirks() const { return quirks_; } + + // Informs the plugin that the view it is in has gained or lost focus. + void SetContentAreaHasFocus(bool has_focus); + +#if defined(OS_MACOSX) + // Informs the plugin that the geometry has changed, as with UpdateGeometry, + // but also includes the new buffer context for that new geometry. + void UpdateGeometryAndContext(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect, + gfx::NativeDrawingContext context); + // Informs the delegate that the plugin called NPN_Invalidate*. Used as a + // trigger for Core Animation drawing. + void PluginDidInvalidate(); + // Returns the delegate currently processing events. + static WebPluginDelegateImpl* GetActiveDelegate(); + // Informs the plugin that the window it is in has gained or lost focus. + void SetWindowHasFocus(bool has_focus); + // Returns whether or not the window the plugin is in has focus. + bool GetWindowHasFocus() const { return containing_window_has_focus_; } + // Informs the plugin that its tab or window has been hidden or shown. + void SetContainerVisibility(bool is_visible); + // Informs the plugin that its containing window's frame has changed. + // Frames are in screen coordinates. + void WindowFrameChanged(const gfx::Rect& window_frame, + const gfx::Rect& view_frame); + // Informs the plugin that IME composition has been confirmed. + void ImeCompositionConfirmed(const string16& text); + // Informs the delegate that the plugin set a Carbon ThemeCursor. + void SetThemeCursor(ThemeCursor cursor); + // Informs the delegate that the plugin set a Carbon Cursor. + void SetCursor(const Cursor* cursor); + // Informs the delegate that the plugin set a Cocoa NSCursor. + void SetNSCursor(NSCursor* cursor); + +#ifndef NP_NO_CARBON + // Indicates that it's time to send the plugin a null event. + void FireIdleEvent(); +#endif +#endif // OS_MACOSX + + gfx::PluginWindowHandle windowed_handle() const { + return windowed_handle_; + } + +#if defined(OS_MACOSX) + // Allow setting a "fake" window handle to associate this plug-in with + // an IOSurface in the browser. Used for accelerated drawing surfaces. + void set_windowed_handle(gfx::PluginWindowHandle handle); +#endif + +#if defined(USE_X11) + void SetWindowlessShmPixmap(XID shm_pixmap) { + windowless_shm_pixmap_ = shm_pixmap; + } +#endif + + private: + friend class DeleteTask; + friend class webkit_glue::WebPluginDelegate; + + WebPluginDelegateImpl(gfx::PluginWindowHandle containing_view, + NPAPI::PluginInstance *instance); + ~WebPluginDelegateImpl(); + + // Called by Initialize() for platform-specific initialization. + // If this returns false, the plugin shouldn't be started--see Initialize(). + bool PlatformInitialize(); + + // Called by DestroyInstance(), used for platform-specific destruction. + void PlatformDestroyInstance(); + + //-------------------------- + // used for windowed plugins + void WindowedUpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + // Create the native window. + // Returns true if the window is created (or already exists). + // Returns false if unable to create the window. + bool WindowedCreatePlugin(); + + // Destroy the native window. + void WindowedDestroyWindow(); + + // Reposition the native window to be in sync with the given geometry. + // Returns true if the native window has moved or been clipped differently. + bool WindowedReposition(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + + // Tells the plugin about the current state of the window. + // See NPAPI NPP_SetWindow for more information. + void WindowedSetWindow(); + +#if defined(OS_WIN) + // Registers the window class for our window + ATOM RegisterNativeWindowClass(); + + // Our WndProc functions. + static LRESULT CALLBACK DummyWindowProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK NativeWndProc( + HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + static LRESULT CALLBACK FlashWindowlessWndProc( + HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + + // Used for throttling Flash messages. + static void ClearThrottleQueueForWindow(HWND window); + static void OnThrottleMessage(); + static void ThrottleMessage(WNDPROC proc, HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif + + //---------------------------- + // used for windowless plugins + void WindowlessUpdateGeometry(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + void WindowlessPaint(gfx::NativeDrawingContext hdc, const gfx::Rect& rect); + + // Tells the plugin about the current state of the window. + // See NPAPI NPP_SetWindow for more information. + void WindowlessSetWindow(); + + // Informs the plugin that it has gained or lost keyboard focus (on the Mac, + // this just means window first responder status). + void SetPluginHasFocus(bool focused); + + // Handles the platform specific details of setting plugin focus. Returns + // false if the platform cancelled the focus tranfer. + bool PlatformSetPluginHasFocus(bool focused); + + //----------------------------------------- + // used for windowed and windowless plugins + + // Does platform-specific event handling. Arguments and return are identical + // to HandleInputEvent. + bool PlatformHandleInputEvent(const WebKit::WebInputEvent& event, + WebKit::WebCursorInfo* cursor_info); + + NPAPI::PluginInstance* instance() { return instance_.get(); } + + // Closes down and destroys our plugin instance. + void DestroyInstance(); + + + // used for windowed plugins + // Note: on Mac OS X, the only time the windowed handle is non-zero + // is the case of accelerated rendering, which uses a fake window handle to + // identify itself back to the browser. It still performs all of its + // work offscreen. + gfx::PluginWindowHandle windowed_handle_; + gfx::Rect windowed_last_pos_; + + bool windowed_did_set_window_; + + // used by windowed and windowless plugins + bool windowless_; + + webkit_glue::WebPlugin* plugin_; + scoped_refptr instance_; + +#if defined(OS_WIN) + // Original wndproc before we subclassed. + WNDPROC plugin_wnd_proc_; + + // Used to throttle WM_USER+1 messages in Flash. + uint32 last_message_; + bool is_calling_wndproc; + + // The current keyboard layout of this process and the main thread ID of the + // browser process. These variables are used for synchronizing the keyboard + // layout of this process with the one of the browser process. + HKL keyboard_layout_; + int parent_thread_id_; +#endif // defined(OS_WIN) + +#if defined(USE_X11) + // The SHM pixmap for a windowless plugin. + XID windowless_shm_pixmap_; + + // The pixmap we're drawing into, for a windowless plugin. + GdkPixmap* pixmap_; + double first_event_time_; + + // On Linux some plugins assume that the GtkSocket container is in the same + // process. So we create a GtkPlug to plug into the browser's container, and + // a GtkSocket to hold the plugin. We then send the GtkPlug to the browser + // process. + GtkWidget* plug_; + GtkWidget* socket_; + + // Ensure pixmap_ exists and is at least width by height pixels. + void EnsurePixmapAtLeastSize(int width, int height); +#endif + + gfx::PluginWindowHandle parent_; + NPWindow window_; + gfx::Rect window_rect_; + gfx::Rect clip_rect_; + int quirks_; + +#if defined(OS_WIN) + // Windowless plugins don't have keyboard focus causing issues with the + // plugin not receiving keyboard events if the plugin enters a modal + // loop like TrackPopupMenuEx or MessageBox, etc. + // This is a basic issue with windows activation and focus arising due to + // the fact that these windows are created by different threads. Activation + // and focus are thread specific states, and if the browser has focus, + // the plugin may not have focus. + // To fix a majority of these activation issues we create a dummy visible + // child window to which we set focus whenever the windowless plugin + // receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent. + + HWND dummy_window_for_activation_; + bool CreateDummyWindowForActivation(); + + // Returns true if the event passed in needs to be tracked for a potential + // modal loop. + static bool ShouldTrackEventForModalLoops(NPEvent* event); + + // The message filter hook procedure, which tracks modal loops entered by + // a plugin in the course of a NPP_HandleEvent call. + static LRESULT CALLBACK HandleEventMessageFilterHook(int code, WPARAM wParam, + LPARAM lParam); + + // TrackPopupMenu interceptor. Parameters are the same as the Win32 function + // TrackPopupMenu. + static BOOL WINAPI TrackPopupMenuPatch(HMENU menu, unsigned int flags, int x, + int y, int reserved, HWND window, + const RECT* rect); + + // SetCursor interceptor for windowless plugins. + static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor); + + // RegEnumKeyExW interceptor. + static LONG WINAPI RegEnumKeyExWPatch( + HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved, + LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time); + + // The mouse hook proc which handles mouse capture in windowed plugins. + static LRESULT CALLBACK MouseHookProc(int code, WPARAM wParam, + LPARAM lParam); + + // Calls SetCapture/ReleaseCapture based on the message type. + static void HandleCaptureForMessage(HWND window, UINT message); + +#elif defined(OS_MACOSX) + // Sets window_rect_ to |rect| + void SetPluginRect(const gfx::Rect& rect); + // Sets content_area_origin to |origin| + void SetContentAreaOrigin(const gfx::Point& origin); + // Updates everything that depends on the plugin's absolute screen location. + void PluginScreenLocationChanged(); + // Updates anything that depends on plugin visibility. + void PluginVisibilityChanged(); + + // Enables/disables IME. + void SetImeEnabled(bool enabled); + + // Informs the browser about the updated accelerated drawing surface. + void UpdateAcceleratedSurface(); + + // Uses a CARenderer to draw the plug-in's layer in our OpenGL surface. + void DrawLayerInSurface(); + +#ifndef NP_NO_CARBON + // Moves our dummy window to match the current screen location of the plugin. + void UpdateDummyWindowBounds(const gfx::Point& plugin_origin); + +#ifndef NP_NO_QUICKDRAW + // Sets the mode used for QuickDraw plugin drawing. If enabled is true the + // plugin draws into a GWorld that's not connected to a window (the faster + // path), otherwise the plugin draws into our invisible dummy window (which is + // slower, since the call we use to scrape the window contents is much more + // expensive than copying between GWorlds). + void SetQuickDrawFastPathEnabled(bool enabled); +#endif + + // Adjusts the idle event rate for a Carbon plugin based on its current + // visibility. + void UpdateIdleEventRate(); +#endif // !NP_NO_CARBON + + CGContextRef buffer_context_; // Weak ref. + +#ifndef NP_NO_CARBON + NP_CGContext np_cg_context_; +#endif +#ifndef NP_NO_QUICKDRAW + NP_Port qd_port_; + scoped_ptr qd_manager_; + base::TimeTicks fast_path_enable_tick_; +#endif + + CALayer* layer_; // Used for CA drawing mode. Weak, retained by plug-in. + webkit_glue::WebPluginAcceleratedSurface* surface_; // Weak ref. + CARenderer* renderer_; // Renders layer_ to surface_. + scoped_ptr > redraw_timer_; + + // The upper-left corner of the web content area in screen coordinates, + // relative to an upper-left (0,0). + gfx::Point content_area_origin_; + + bool containing_window_has_focus_; + bool initial_window_focus_; + bool container_is_visible_; + bool have_called_set_window_; + + gfx::Rect cached_clip_rect_; + + bool ime_enabled_; + + scoped_ptr external_drag_tracker_; +#endif // OS_MACOSX + + // Called by the message filter hook when the plugin enters a modal loop. + void OnModalLoopEntered(); + + // Returns true if the message passed in corresponds to a user gesture. + static bool IsUserGesture(const WebKit::WebInputEvent& event); + + // The url with which the plugin was instantiated. + std::string plugin_url_; + +#if defined(OS_WIN) + // Indicates the end of a user gesture period. + void OnUserGestureEnd(); + + // Handle to the message filter hook + HHOOK handle_event_message_filter_hook_; + + // Event which is set when the plugin enters a modal loop in the course + // of a NPP_HandleEvent call. + HANDLE handle_event_pump_messages_event_; + + // This flag indicates whether we started tracking a user gesture message. + bool user_gesture_message_posted_; + + // Runnable Method Factory used to invoke the OnUserGestureEnd method + // asynchronously. + ScopedRunnableMethodFactory user_gesture_msg_factory_; + + // Handle to the mouse hook installed for certain windowed plugins like + // flash. + HHOOK mouse_hook_; +#endif + + // Holds the depth of the HandleEvent callstack. + int handle_event_depth_; + + // Holds the current cursor set by the windowless plugin. + WebCursor current_windowless_cursor_; + + // Set to true initially and indicates if this is the first npp_setwindow + // call received by the plugin. + bool first_set_window_call_; + + // True if the plugin thinks it has keyboard focus + bool plugin_has_focus_; + // True if the plugin element has focus within the web content, regardless of + // whether its containing view currently has focus. + bool has_webkit_focus_; + // True if the containing view currently has focus. + // Initially set to true so that plugin focus still works in environments + // where SetContentAreaHasFocus is never called. See + // https://bugs.webkit.org/show_bug.cgi?id=46013 for details. + bool containing_view_has_focus_; + + // True if NPP_New did not return an error. + bool creation_succeeded_; + + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegateImpl); +}; + +#endif // WEBKIT_GLUE_PLUGINS_WEBPLUGIN_DELEGATE_IMPL_H_ diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc new file mode 100644 index 0000000..609b41e --- /dev/null +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -0,0 +1,767 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/webplugin_delegate_impl.h" + +#include +#include + +#include +#include + +#include "base/basictypes.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/process_util.h" +#include "base/metrics/stats_counters.h" +#include "base/string_util.h" +#include "gfx/blit.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "webkit/glue/plugins/gtk_plugin_container.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/plugins/plugin_lib.h" +#include "webkit/glue/plugins/plugin_list.h" +#include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/webplugin.h" +#include "webkit/glue/webkit_glue.h" + +#include "third_party/npapi/bindings/npapi_x11.h" + +using WebKit::WebCursorInfo; +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; + +WebPluginDelegateImpl::WebPluginDelegateImpl( + gfx::PluginWindowHandle containing_view, + NPAPI::PluginInstance *instance) + : windowed_handle_(0), + windowed_did_set_window_(false), + windowless_(false), + plugin_(NULL), + instance_(instance), + windowless_shm_pixmap_(None), + pixmap_(NULL), + first_event_time_(-1.0), + plug_(NULL), + socket_(NULL), + parent_(containing_view), + quirks_(0), + handle_event_depth_(0), + first_set_window_call_(true), + plugin_has_focus_(false), + has_webkit_focus_(false), + containing_view_has_focus_(true), + creation_succeeded_(false) { + memset(&window_, 0, sizeof(window_)); + if (instance_->mime_type() == "application/x-shockwave-flash") { + // Flash is tied to Firefox's whacky behavior with windowless plugins. See + // comments in WindowlessPaint. + // TODO(viettrungluu): PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK: Don't allow + // right-clicks in windowless content since Flash 10.1 (initial release, at + // least) hangs in that case. Remove this once Flash is fixed. + quirks_ |= PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW + | PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW + | PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK; + } + + // TODO(evanm): I played with this for quite a while but couldn't + // figure out a way to make Flash not crash unless I didn't call + // NPP_SetWindow. + // However, after piman's grand refactor of windowed plugins, maybe + // this is no longer necessary. + quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; +} + +WebPluginDelegateImpl::~WebPluginDelegateImpl() { + DestroyInstance(); + + if (!windowless_) + WindowedDestroyWindow(); + + if (window_.ws_info) { + // We only ever use ws_info as an NPSetWindowCallbackStruct. + delete static_cast(window_.ws_info); + } + + if (pixmap_) { + g_object_unref(pixmap_); + pixmap_ = NULL; + } +} + +bool WebPluginDelegateImpl::PlatformInitialize() { + gfx::PluginWindowHandle handle = + windowless_ ? 0 : gtk_plug_get_id(GTK_PLUG(plug_)); + plugin_->SetWindow(handle); + return true; +} + +void WebPluginDelegateImpl::PlatformDestroyInstance() { + // Nothing to do here. +} + +void WebPluginDelegateImpl::Paint(WebKit::WebCanvas* canvas, + const gfx::Rect& rect) { + if (!windowless_) + return; + cairo_t* context = canvas->beginPlatformPaint(); + WindowlessPaint(context, rect); + canvas->endPlatformPaint(); +} + +void WebPluginDelegateImpl::Print(cairo_t* context) { + NOTIMPLEMENTED(); +} + +void WebPluginDelegateImpl::InstallMissingPlugin() { + NOTIMPLEMENTED(); +} + +bool WebPluginDelegateImpl::WindowedCreatePlugin() { + DCHECK(!windowed_handle_); + DCHECK(!plug_); + + // NPP_GetValue() might write 4 bytes of data to this variable. Don't use a + // single byte bool, use an int instead and make sure it is initialized. + int xembed = 0; + NPError err = instance_->NPP_GetValue(NPPVpluginNeedsXEmbed, &xembed); + if (err != NPERR_NO_ERROR || !xembed) { + NOTIMPLEMENTED() << " windowed plugin but without xembed. " + "See http://code.google.com/p/chromium/issues/detail?id=38229"; + return false; + } + + // Passing 0 as the socket XID creates a plug without plugging it in a socket + // yet, so that it can be latter added with gtk_socket_add_id(). + plug_ = gtk_plug_new(0); + gtk_widget_show(plug_); + socket_ = gtk_socket_new(); + gtk_widget_show(socket_); + gtk_container_add(GTK_CONTAINER(plug_), socket_); + gtk_widget_show_all(plug_); + + // Prevent the plug from being destroyed if the browser kills the container + // window. + g_signal_connect(plug_, "delete-event", G_CALLBACK(gtk_true), NULL); + // Prevent the socket from being destroyed when the plugin removes itself. + g_signal_connect(socket_, "plug_removed", G_CALLBACK(gtk_true), NULL); + + windowed_handle_ = gtk_socket_get_id(GTK_SOCKET(socket_)); + + window_.window = reinterpret_cast(windowed_handle_); + + if (!window_.ws_info) + window_.ws_info = new NPSetWindowCallbackStruct; + NPSetWindowCallbackStruct* extra = + static_cast(window_.ws_info); + extra->display = GDK_DISPLAY(); + extra->visual = DefaultVisual(GDK_DISPLAY(), 0); + extra->depth = DefaultDepth(GDK_DISPLAY(), 0); + extra->colormap = DefaultColormap(GDK_DISPLAY(), 0); + + return true; +} + +void WebPluginDelegateImpl::WindowedDestroyWindow() { + if (plug_) { + plugin_->WillDestroyWindow(gtk_plug_get_id(GTK_PLUG(plug_))); + + gtk_widget_destroy(plug_); + plug_ = NULL; + socket_ = NULL; + windowed_handle_ = 0; + } +} + +bool WebPluginDelegateImpl::WindowedReposition( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + if (window_rect == window_rect_ && clip_rect == clip_rect_) + return false; + + window_rect_ = window_rect; + clip_rect_ = clip_rect; + + return true; +} + +void WebPluginDelegateImpl::WindowedSetWindow() { + if (!instance_) + return; + + if (!windowed_handle_) { + NOTREACHED(); + return; + } + + // See https://bugzilla.mozilla.org/show_bug.cgi?id=108347 + // If we call NPP_SetWindow with a <= 0 width or height, problems arise in + // Flash (and possibly other plugins). + // TODO(piman): the Mozilla code suggests that for the Java plugin, we should + // still call NPP_SetWindow in that case. We need to verify that. + if (window_rect_.width() <= 0 || window_rect_.height() <= 0) { + return; + } + + instance()->set_window_handle(windowed_handle_); + + DCHECK(!instance()->windowless()); + + window_.clipRect.top = clip_rect_.y(); + window_.clipRect.left = clip_rect_.x(); + window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); + window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); + window_.height = window_rect_.height(); + window_.width = window_rect_.width(); + window_.x = window_rect_.x(); + window_.y = window_rect_.y(); + + //window_.window = windowed_handle_; + window_.type = NPWindowTypeWindow; + + // Reset this flag before entering the instance in case of side-effects. + windowed_did_set_window_ = true; + + NPError err = instance()->NPP_SetWindow(&window_); + DCHECK(err == NPERR_NO_ERROR); +} + +void WebPluginDelegateImpl::WindowlessUpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + // Only resend to the instance if the geometry has changed. + if (window_rect == window_rect_ && clip_rect == clip_rect_) + return; + + clip_rect_ = clip_rect; + window_rect_ = window_rect; + WindowlessSetWindow(); +} + +void WebPluginDelegateImpl::EnsurePixmapAtLeastSize(int width, int height) { + if (pixmap_) { + gint cur_width, cur_height; + gdk_drawable_get_size(pixmap_, &cur_width, &cur_height); + if (cur_width >= width && cur_height >= height) + return; // We are already the appropriate size. + + // Otherwise, we need to recreate ourselves. + g_object_unref(pixmap_); + pixmap_ = NULL; + } + + // |sys_visual| is owned by gdk; we shouldn't free it. + GdkVisual* sys_visual = gdk_visual_get_system(); + pixmap_ = gdk_pixmap_new(NULL, // use width/height/depth params + std::max(1, width), std::max(1, height), + sys_visual->depth); + GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), + FALSE); + gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap_), colormap); + // The GdkDrawable now owns the GdkColormap. + g_object_unref(colormap); +} + +#ifdef DEBUG_RECTANGLES +namespace { + +// Draw a rectangle on a Cairo context. +// Useful for debugging various rectangles involved in drawing plugins. +void DrawDebugRectangle(cairo_t* cairo, + const gfx::Rect& rect, + float r, float g, float b) { + cairo_set_source_rgba(cairo, r, g, b, 0.5); + cairo_rectangle(cairo, rect.x(), rect.y(), + rect.width(), rect.height()); + cairo_stroke(cairo); +} + +} // namespace +#endif + +void WebPluginDelegateImpl::WindowlessPaint(cairo_t* context, + const gfx::Rect& damage_rect) { + // Compare to: + // http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp: + // nsPluginInstanceOwner::Renderer::NativeDraw(). + + DCHECK(context); + + // TODO(darin): we should avoid calling NPP_SetWindow here since it may + // cause page layout to be invalidated. + + // The actual dirty region is just the intersection of the plugin window and + // the clip window with the damage region. However, the plugin wants to draw + // relative to the containing window's origin, so our pixmap must be from the + // window's origin down to the bottom-right edge of the dirty region. + // + // Typical case: + // X-----------------------------------+-----------------------------+ + // | | | + // | pixmap +-------------------+ | + // | | damage | window | + // | | | | + // | +---+-------------------+-------------+ | + // | | | | clip | | + // | +---+---+-------------------+----------+ | | + // | | | | | | | | + // | | | | draw | | | | + // | | | | | | | | + // +-------+---+---+-------------------+----------+--+ | + // | | | | | | + // | | +-------------------+ | | + // | | | | + // | | plugin | | + // | +--------------------------------------+ | + // | | + // | | + // +-----------------------------------------------------------------+ + // X = origin + // + // NPAPI doesn't properly define which coordinates each of + // - window.clipRect, window.x and window.y in the SetWindow call + // - x and y in GraphicsExpose HandleEvent call + // are relative to, nor does it define what the pixmap is relative to. + // + // Any sane values for them just don't work with the flash plugin. Firefox + // has some interesting behavior. Experiments showed that: + // - window.clipRect is always in the same space as window.x and window.y + // - in the first SetWindow call, or when scrolling, window.x and window.y are + // the coordinates of the plugin relative to the window. + // - whenever only a part of the plugin is drawn, Firefox issues a SetWindow + // call before each GraphicsExpose event, that sets the drawing origin to + // (0, 0) as if the plugin was scrolled to be partially out of the view. The + // GraphicsExpose event has coordinates relative to the "window" (assuming + // that virtual scroll). The pixmap is also relative to the window. It always + // sets the clip rect to the draw rect. + // + // Attempts to deviate from that makes Flash render at the wrong place in the + // pixmap, or render the wrong pixels. + // + // Flash plugin: + // X-----------------------------------------------------------------+ + // | | + // | +-------------------+ "real" window | + // | | damage | | + // | | | | + // | +---+-------------------+-------------+ | + // | | | | "real" clip | | + // | +---+---O===================#==========#==#===============# + // | | | H draw | | | H + // | | | H = pixmap | | | H + // | | | H = "apparent" clip | | | H + // | + +---#-------------------+----------+--+ H + // | | H | | H + // | | H-------------------+ | H + // | | H | H + // | | H plugin | H + // | +-------#------------------------------+ H + // | H H + // | H "apparent" window H + // +---------------#=================================================# + // X = "real" origin + // O = "apparent" origin + // "real" means as seen by Chrome + // "apparent" means as seen by the plugin. + + gfx::Rect draw_rect = window_rect_.Intersect(damage_rect); + + // clip_rect_ is relative to the plugin + gfx::Rect clip_rect_window = clip_rect_; + clip_rect_window.Offset(window_rect_.x(), window_rect_.y()); + draw_rect = draw_rect.Intersect(clip_rect_window); + + // These offsets represent by how much the view is shifted to accomodate + // Flash (the coordinates of X relative to O in the diagram above). + int offset_x = 0; + int offset_y = 0; + if (quirks_ & PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW) { + offset_x = -draw_rect.x(); + offset_y = -draw_rect.y(); + window_.clipRect.top = 0; + window_.clipRect.left = 0; + window_.clipRect.bottom = draw_rect.height(); + window_.clipRect.right = draw_rect.width(); + window_.height = window_rect_.height(); + window_.width = window_rect_.width(); + window_.x = window_rect_.x() - draw_rect.x(); + window_.y = window_rect_.y() - draw_rect.y(); + window_.type = NPWindowTypeDrawable; + DCHECK(window_.ws_info); + NPError err = instance()->NPP_SetWindow(&window_); + DCHECK_EQ(err, NPERR_NO_ERROR); + } + + gfx::Rect pixmap_draw_rect = draw_rect; + pixmap_draw_rect.Offset(offset_x, offset_y); + + gfx::Rect pixmap_rect(0, 0, + pixmap_draw_rect.right(), + pixmap_draw_rect.bottom()); + + // Construct the paint message, targeting the pixmap. + NPEvent np_event = {0}; + XGraphicsExposeEvent &event = np_event.xgraphicsexpose; + event.type = GraphicsExpose; + event.x = pixmap_draw_rect.x(); + event.y = pixmap_draw_rect.y(); + event.width = pixmap_draw_rect.width(); + event.height = pixmap_draw_rect.height(); + event.display = GDK_DISPLAY(); + + if (windowless_shm_pixmap_ != None) { + Pixmap pixmap = None; + GC xgc = NULL; + Display* display = event.display; + gfx::Rect plugin_draw_rect = draw_rect; + + // Make plugin_draw_rect relative to the plugin window. + plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y()); + + // In case the drawing area does not start with the plugin window origin, + // we can not let the plugin directly draw over the shared memory pixmap. + if (plugin_draw_rect.x() != pixmap_draw_rect.x() || + plugin_draw_rect.y() != pixmap_draw_rect.y()) { + pixmap = XCreatePixmap(display, windowless_shm_pixmap_, + std::max(1, pixmap_rect.width()), + std::max(1, pixmap_rect.height()), + DefaultDepth(display, 0)); + xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL); + // Copy the current image into the pixmap, so the plugin can draw over it. + XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc, + plugin_draw_rect.x(), plugin_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + pixmap_draw_rect.x(), pixmap_draw_rect.y()); + + event.drawable = pixmap; + } else { + event.drawable = windowless_shm_pixmap_; + } + + // Tell the plugin to paint into the pixmap. + static base::StatsRate plugin_paint("Plugin.Paint"); + base::StatsScope scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); + + if (pixmap != None) { + // Copy the rendered image pixmap back into the shm pixmap + // and thus the drawing buffer. + XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc, + pixmap_draw_rect.x(), pixmap_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + plugin_draw_rect.x(), plugin_draw_rect.y()); + XSync(display, FALSE); + if (xgc) + XFreeGC(display, xgc); + XFreePixmap(display, pixmap); + } else { + XSync(display, FALSE); + } + } else { + EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); + + // Copy the current image into the pixmap, so the plugin can draw over + // this background. + cairo_t* cairo = gdk_cairo_create(pixmap_); + BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); + cairo_destroy(cairo); + + event.drawable = GDK_PIXMAP_XID(pixmap_); + + // Tell the plugin to paint into the pixmap. + static base::StatsRate plugin_paint("Plugin.Paint"); + base::StatsScope scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); + + cairo_save(context); + // Now copy the rendered image pixmap back into the drawing buffer. + gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); + cairo_rectangle(context, draw_rect.x(), draw_rect.y(), + draw_rect.width(), draw_rect.height()); + cairo_clip(context); + cairo_paint(context); + +#ifdef DEBUG_RECTANGLES + // Draw some debugging rectangles. + // Pixmap rect = blue. + DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); + // Drawing rect = red. + DrawDebugRectangle(context, draw_rect, 1, 0, 0); +#endif + cairo_restore(context); + } +} + +void WebPluginDelegateImpl::WindowlessSetWindow() { + if (!instance()) + return; + + if (window_rect_.IsEmpty()) // wait for geometry to be set. + return; + + DCHECK(instance()->windowless()); + // Mozilla docs say that this window param is not used for windowless + // plugins; rather, the window is passed during the GraphicsExpose event. + DCHECK(window_.window == 0); + + window_.clipRect.top = clip_rect_.y() + window_rect_.y(); + window_.clipRect.left = clip_rect_.x() + window_rect_.x(); + window_.clipRect.bottom = + clip_rect_.y() + clip_rect_.height() + window_rect_.y(); + window_.clipRect.right = + clip_rect_.x() + clip_rect_.width() + window_rect_.x(); + window_.height = window_rect_.height(); + window_.width = window_rect_.width(); + window_.x = window_rect_.x(); + window_.y = window_rect_.y(); + window_.type = NPWindowTypeDrawable; + + if (!window_.ws_info) + window_.ws_info = new NPSetWindowCallbackStruct; + NPSetWindowCallbackStruct* extra = + static_cast(window_.ws_info); + extra->display = GDK_DISPLAY(); + extra->visual = DefaultVisual(GDK_DISPLAY(), 0); + extra->depth = DefaultDepth(GDK_DISPLAY(), 0); + extra->colormap = DefaultColormap(GDK_DISPLAY(), 0); + + NPError err = instance()->NPP_SetWindow(&window_); + DCHECK(err == NPERR_NO_ERROR); + if (quirks_ & PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW) { + // After a NPP_SetWindow, Flash cancels its timer that generates the + // invalidates until it gets a paint event, but doesn't explicitly call + // NPP_InvalidateRect. + plugin_->InvalidateRect(clip_rect_); + } +} + +bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { + DCHECK(instance()->windowless()); + + NPEvent np_event = {0}; + XFocusChangeEvent &event = np_event.xfocus; + event.type = focused ? FocusIn : FocusOut; + event.display = GDK_DISPLAY(); + // Same values as Firefox. .serial and .window stay 0. + event.mode = -1; + event.detail = NotifyDetailNone; + instance()->NPP_HandleEvent(&np_event); + return true; +} + +// Converts a WebInputEvent::Modifiers bitfield into a +// corresponding X modifier state. +static int GetXModifierState(int modifiers) { + int x_state = 0; + if (modifiers & WebInputEvent::ControlKey) + x_state |= ControlMask; + if (modifiers & WebInputEvent::ShiftKey) + x_state |= ShiftMask; + if (modifiers & WebInputEvent::AltKey) + x_state |= Mod1Mask; + if (modifiers & WebInputEvent::MetaKey) + x_state |= Mod2Mask; + if (modifiers & WebInputEvent::LeftButtonDown) + x_state |= Button1Mask; + if (modifiers & WebInputEvent::MiddleButtonDown) + x_state |= Button2Mask; + if (modifiers & WebInputEvent::RightButtonDown) + x_state |= Button3Mask; + // TODO(piman@google.com): There are other modifiers, e.g. Num Lock, that + // should be set (and Firefox does), but we didn't keep the information in + // the WebKit event. + return x_state; +} + +static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, + Time timestamp, + NPEvent *np_event) { + np_event->xany.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + + int modifier_state = GetXModifierState(event.modifiers); + + Window root = GDK_ROOT_WINDOW(); + switch (event.type) { + case WebInputEvent::MouseMove: { + np_event->type = MotionNotify; + XMotionEvent &motion_event = np_event->xmotion; + motion_event.root = root; + motion_event.time = timestamp; + motion_event.x = event.x; + motion_event.y = event.y; + motion_event.x_root = event.globalX; + motion_event.y_root = event.globalY; + motion_event.state = modifier_state; + motion_event.is_hint = NotifyNormal; + motion_event.same_screen = True; + break; + } + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: { + if (event.type == WebInputEvent::MouseEnter) { + np_event->type = EnterNotify; + } else { + np_event->type = LeaveNotify; + } + XCrossingEvent &crossing_event = np_event->xcrossing; + crossing_event.root = root; + crossing_event.time = timestamp; + crossing_event.x = event.x; + crossing_event.y = event.y; + crossing_event.x_root = event.globalX; + crossing_event.y_root = event.globalY; + crossing_event.mode = -1; // This is what Firefox sets it to. + crossing_event.detail = NotifyDetailNone; + crossing_event.same_screen = True; + // TODO(piman@google.com): set this to the correct value. Firefox does. I + // don't know where to get the information though, we get focus + // notifications, but no unfocus. + crossing_event.focus = 0; + crossing_event.state = modifier_state; + break; + } + case WebInputEvent::MouseUp: + case WebInputEvent::MouseDown: { + if (event.type == WebInputEvent::MouseDown) { + np_event->type = ButtonPress; + } else { + np_event->type = ButtonRelease; + } + XButtonEvent &button_event = np_event->xbutton; + button_event.root = root; + button_event.time = timestamp; + button_event.x = event.x; + button_event.y = event.y; + button_event.x_root = event.globalX; + button_event.y_root = event.globalY; + button_event.state = modifier_state; + switch (event.button) { + case WebMouseEvent::ButtonLeft: + button_event.button = Button1; + break; + case WebMouseEvent::ButtonMiddle: + button_event.button = Button2; + break; + case WebMouseEvent::ButtonRight: + button_event.button = Button3; + break; + default: + NOTREACHED(); + } + button_event.same_screen = True; + break; + } + default: + NOTREACHED(); + return false; + } + return true; +} + +static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event, + Time timestamp, + NPEvent *np_event) { + np_event->xany.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + + switch (event.type) { + case WebKeyboardEvent::KeyDown: + np_event->type = KeyPress; + break; + case WebKeyboardEvent::KeyUp: + np_event->type = KeyRelease; + break; + default: + NOTREACHED(); + return false; + } + XKeyEvent &key_event = np_event->xkey; + key_event.send_event = False; + key_event.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + // TODO(piman@google.com): is this right for multiple screens ? + key_event.root = DefaultRootWindow(key_event.display); + key_event.time = timestamp; + // NOTE: We don't have the correct information for x/y/x_root/y_root. Firefox + // doesn't have it either, so we pass the same values. + key_event.x = 0; + key_event.y = 0; + key_event.x_root = -1; + key_event.y_root = -1; + key_event.state = GetXModifierState(event.modifiers); + key_event.keycode = event.nativeKeyCode; + key_event.same_screen = True; + return true; +} + +static bool NPEventFromWebInputEvent(const WebInputEvent& event, + Time timestamp, + NPEvent* np_event) { + switch (event.type) { + case WebInputEvent::MouseMove: + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: + case WebInputEvent::MouseDown: + case WebInputEvent::MouseUp: + if (event.size < sizeof(WebMouseEvent)) { + NOTREACHED(); + return false; + } + return NPEventFromWebMouseEvent( + *static_cast(&event), timestamp, np_event); + case WebInputEvent::KeyDown: + case WebInputEvent::KeyUp: + if (event.size < sizeof(WebKeyboardEvent)) { + NOTREACHED(); + return false; + } + return NPEventFromWebKeyboardEvent( + *static_cast(&event), timestamp, np_event); + default: + return false; + } +} + +bool WebPluginDelegateImpl::PlatformHandleInputEvent( + const WebInputEvent& event, WebCursorInfo* cursor_info) { + + if (first_event_time_ < 0.0) + first_event_time_ = event.timeStampSeconds; + Time timestamp = static_cast