summaryrefslogtreecommitdiff
path: root/chromium/content/browser/renderer_host
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/renderer_host')
-rw-r--r--chromium/content/browser/renderer_host/DEPS4
-rw-r--r--chromium/content/browser/renderer_host/backing_store_gtk.cc22
-rw-r--r--chromium/content/browser/renderer_host/backing_store_gtk.h6
-rw-r--r--chromium/content/browser/renderer_host/backing_store_win.cc9
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h8
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.cc13
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.h2
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc147
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h10
-rw-r--r--chromium/content/browser/renderer_host/frame_memory_manager.cc66
-rw-r--r--chromium/content/browser/renderer_host/frame_memory_manager.h44
-rw-r--r--chromium/content/browser/renderer_host/generic_touch_gesture_android.cc62
-rw-r--r--chromium/content/browser/renderer_host/generic_touch_gesture_android.h48
-rw-r--r--chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc8
-rw-r--r--chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc2
-rw-r--r--chromium/content/browser/renderer_host/gtk_window_utils.cc7
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/OWNERS3
-rw-r--r--chromium/content/browser/renderer_host/input/browser_input_event.cc47
-rw-r--r--chromium/content/browser/renderer_host/input/browser_input_event.h69
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router.cc336
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router.h144
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc320
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router.cc93
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router.h20
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc666
-rw-r--r--chromium/content/browser/renderer_host/input/input_ack_handler.h41
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue.cc183
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue.h82
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue_client.h35
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue_unittest.cc363
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h9
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h19
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_unittest.cc225
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_unittest.h83
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc77
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.h77
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc148
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h126
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc7
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h9
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc603
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h44
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc171
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.h2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_posix.h2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc32
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc30
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h13
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.h5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.cc251
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.h2
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc96
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.h6
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.cc55
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.h10
-rw-r--r--chromium/content/browser/renderer_host/media/mock_media_observer.h5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc604
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h157
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc567
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc72
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h16
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc48
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc635
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h217
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc136
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h4
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc30
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h15
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc19
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event.cc2
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc5
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc12
-rw-r--r--chromium/content/browser/renderer_host/overscroll_configuration.cc18
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc65
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h13
-rw-r--r--chromium/content/browser/renderer_host/p2p/OWNERS3
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc8
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc9
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h17
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc34
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc45
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.h40
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc14
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h6
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc76
-rw-r--r--chromium/content/browser/renderer_host/pepper/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc21
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h13
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc64
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h26
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc13
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc38
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc23
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h18
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc459
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.h194
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc121
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h50
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc93
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc52
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc62
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h27
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc100
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h35
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h148
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc979
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h223
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc30
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.h48
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.cc49
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.h18
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc247
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h15
-rw-r--r--chromium/content/browser/renderer_host/render_sandbox_host_linux.cc11
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h17
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc5
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.h3
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc104
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h44
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc52
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc10
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc232
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h76
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc127
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc82
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h22
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc578
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h102
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc278
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc30
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h11
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc53
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc56
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.h12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.cc24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.h18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h26
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm75
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm150
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.cc161
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.h24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc14
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_calculator.cc28
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_calculator.h29
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc61
-rw-r--r--chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h52
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc8
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h9
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc8
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.h4
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc37
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_calculator.h28
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller.cc84
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller.h57
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc (renamed from chromium/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc)34
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.cc14
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.h15
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac.mm4
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.mm2
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc75
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h52
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc8
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h8
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc4
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc147
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.h4
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurax11.cc106
208 files changed, 9967 insertions, 4602 deletions
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 34decdb0223..0848d364726 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -5,10 +5,6 @@ include_rules = [
"+third_party/zlib",
"+third_party/libyuv",
- # For single-process mode.
- "+content/renderer/render_process_impl.h",
- "+content/renderer/render_thread_impl.h",
-
# The renderer_host files should only call upwards in the layering via the
# delegate interfaces.
"-content/browser/web_contents",
diff --git a/chromium/content/browser/renderer_host/backing_store_gtk.cc b/chromium/content/browser/renderer_host/backing_store_gtk.cc
index 62365bed873..2eed33ace2f 100644
--- a/chromium/content/browser/renderer_host/backing_store_gtk.cc
+++ b/chromium/content/browser/renderer_host/backing_store_gtk.cc
@@ -29,10 +29,10 @@
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/gtk/gtk_signal.h"
-#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/x/x11_types.h"
#include "ui/surface/transport_dib.h"
namespace content {
@@ -59,7 +59,7 @@ static const int kMaxVideoLayerSize = 23170;
// Destroys the image and the associated shared memory structures. This is a
// helper function for code using shared memory.
-void DestroySharedImage(Display* display,
+void DestroySharedImage(XDisplay* display,
XImage* image,
XShmSegmentInfo* shminfo) {
XShmDetach(display, shminfo);
@@ -72,7 +72,7 @@ void DestroySharedImage(Display* display,
// XSyncExtension to push a callback into the X11 event queue and get a
// callback instead of blocking until the event queue is cleared.
//
-// TODO(erg): If ui::GetXDisplay() ever gets fixed to handle multiple Displays,
+// TODO(erg): If gfx::GetXDisplay() ever gets fixed to handle multiple Displays,
// this must be modified to be per Display instead of a Singleton.
class XSyncHandler {
public:
@@ -85,7 +85,7 @@ class XSyncHandler {
}
void PushPaintCounter(TransportDIB* dib,
- Display* display,
+ XDisplay* display,
Picture picture,
Pixmap pixmap,
const base::Closure& completion_callback);
@@ -96,7 +96,7 @@ class XSyncHandler {
// A struct that has cleanup and callback tasks that were queued into the
// future and are run on |g_backing_store_sync_alarm| firing.
struct BackingStoreEvents {
- BackingStoreEvents(TransportDIB* dib, Display* d, Picture pic, Pixmap pix,
+ BackingStoreEvents(TransportDIB* dib, XDisplay* d, Picture pic, Pixmap pix,
const base::Closure& c)
: dib(dib),
display(d),
@@ -109,7 +109,7 @@ class XSyncHandler {
TransportDIB* dib;
// The display we're running on.
- Display* display;
+ XDisplay* display;
// Data to delete.
Picture picture;
@@ -142,7 +142,7 @@ class XSyncHandler {
};
void XSyncHandler::PushPaintCounter(TransportDIB* dib,
- Display* display,
+ XDisplay* display,
Picture picture,
Pixmap pixmap,
const base::Closure& completion_callback) {
@@ -153,7 +153,7 @@ void XSyncHandler::PushPaintCounter(TransportDIB* dib,
// alarm when it is processed.
XSyncValue value;
XSyncIntToValue(&value, 1);
- XSyncChangeCounter(ui::GetXDisplay(),
+ XSyncChangeCounter(gfx::GetXDisplay(),
backing_store_sync_counter_,
value);
}
@@ -164,7 +164,7 @@ XSyncHandler::XSyncHandler()
xsync_error_base_(0),
backing_store_sync_counter_(0),
backing_store_sync_alarm_(0) {
- Display* display = ui::GetXDisplay();
+ XDisplay* display = gfx::GetXDisplay();
if (XSyncQueryExtension(display,
&xsync_event_base_,
&xsync_error_base_)) {
@@ -191,7 +191,7 @@ XSyncHandler::~XSyncHandler() {
if (loaded_extension_)
gdk_window_remove_filter(NULL, &OnEventThunk, this);
- XSync(ui::GetXDisplay(), False);
+ XSync(gfx::GetXDisplay(), False);
while (!backing_store_events_.empty()) {
// We delete the X11 resources we're holding onto. We don't run the
// callbacks because we are shutting down.
@@ -248,7 +248,7 @@ BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
void* visual,
int depth)
: BackingStore(widget, size),
- display_(ui::GetXDisplay()),
+ display_(gfx::GetXDisplay()),
shared_memory_support_(ui::QuerySharedMemorySupport(display_)),
use_render_(ui::QueryRenderSupport(display_)),
visual_(visual),
diff --git a/chromium/content/browser/renderer_host/backing_store_gtk.h b/chromium/content/browser/renderer_host/backing_store_gtk.h
index 0e81597c0b6..29776fcdf67 100644
--- a/chromium/content/browser/renderer_host/backing_store_gtk.h
+++ b/chromium/content/browser/renderer_host/backing_store_gtk.h
@@ -12,7 +12,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/backing_store.h"
#include "content/common/content_export.h"
-#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_types.h"
namespace gfx {
class Point;
@@ -39,7 +39,7 @@ class CONTENT_EXPORT BackingStoreGtk : public BackingStore {
virtual ~BackingStoreGtk();
- Display* display() const { return display_; }
+ XDisplay* display() const { return display_; }
XID root_window() const { return root_window_; }
// Copy from the server-side backing store to the target window
@@ -79,7 +79,7 @@ class CONTENT_EXPORT BackingStoreGtk : public BackingStore {
// This is the connection to the X server where this backing store will be
// displayed.
- Display* const display_;
+ XDisplay* const display_;
// What flavor, if any, MIT-SHM (X shared memory) support we have.
const ui::SharedMemorySupport shared_memory_support_;
// If this is true, then we can use Xrender to composite our pixmaps.
diff --git a/chromium/content/browser/renderer_host/backing_store_win.cc b/chromium/content/browser/renderer_host/backing_store_win.cc
index 5ccafbb062b..8e761dd0c32 100644
--- a/chromium/content/browser/renderer_host/backing_store_win.cc
+++ b/chromium/content/browser/renderer_host/backing_store_win.cc
@@ -9,10 +9,10 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_canvas.h"
-#include "ui/base/win/dpi.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/win/dpi.h"
#include "ui/surface/transport_dib.h"
namespace content {
@@ -92,7 +92,7 @@ bool BackingStoreWin::ColorManagementEnabled() {
size_t BackingStoreWin::MemorySize() {
gfx::Size size_in_pixels = gfx::ToCeiledSize(gfx::ScaleSize(size(),
- ui::win::GetDeviceScaleFactor()));
+ gfx::win::GetDeviceScaleFactor()));
return size_in_pixels.GetArea() * (color_depth_ / 8);
}
@@ -104,6 +104,7 @@ void BackingStoreWin::PaintToBackingStore(
float scale_factor,
const base::Closure& completion_callback,
bool* scheduled_completion_callback) {
+ TRACE_EVENT0("content", "BackingStoreWin::PaintToBackingStore");
*scheduled_completion_callback = false;
gfx::Size size_in_pixels = gfx::ToCeiledSize(gfx::ScaleSize(
size(), scale_factor));
@@ -155,6 +156,7 @@ void BackingStoreWin::PaintToBackingStore(
bool BackingStoreWin::CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformBitmap* output) {
+ TRACE_EVENT0("content", "BackingStoreWin::CopyFromBackingStore");
// TODO(kevers): Make sure this works with HiDPI backing stores.
if (!output->Allocate(rect.width(), rect.height(), true))
return false;
@@ -168,10 +170,11 @@ bool BackingStoreWin::CopyFromBackingStore(const gfx::Rect& rect,
void BackingStoreWin::ScrollBackingStore(const gfx::Vector2d& delta,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
+ TRACE_EVENT0("content", "BackingStoreWin::ScrollBackingStore");
// TODO(darin): this doesn't work if delta x() and y() are both non-zero!
DCHECK(delta.x() == 0 || delta.y() == 0);
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
gfx::Rect screen_rect = gfx::ToEnclosingRect(
gfx::ScaleRect(clip_rect, scale));
int dx = static_cast<int>(delta.x() * scale);
diff --git a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
index 1bcc8223e97..e4563375681 100644
--- a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
+++ b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
@@ -26,9 +26,9 @@ bool BasicMouseWheelSmoothScrollGesture::ForwardInputEvents(
if (pixels_scrolled_ >= pixels_to_scroll_)
return false;
- double position_delta = smooth_scroll_calculator_.GetScrollDelta(
+ float position_delta = synthetic_gesture_calculator_.GetDelta(
now,
- RenderWidgetHostImpl::From(host)->GetSyntheticScrollMessageInterval());
+ RenderWidgetHostImpl::From(host)->GetSyntheticGestureMessageInterval());
WebKit::WebMouseWheelEvent event;
diff --git a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h
index adea7a30b74..ba127da05bd 100644
--- a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h
+++ b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h
@@ -6,14 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_BASIC_MOUSE_WHEEL_SMOOTH_SCROLL_GESTURE_
#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+#include "content/port/browser/synthetic_gesture.h"
namespace content {
class RenderWidgetHost;
-class BasicMouseWheelSmoothScrollGesture : public SmoothScrollGesture {
+class BasicMouseWheelSmoothScrollGesture : public SyntheticGesture {
public:
BasicMouseWheelSmoothScrollGesture(bool scroll_down, int pixels_to_scroll,
int mouse_event_x, int mouse_event_y);
@@ -23,7 +23,7 @@ class BasicMouseWheelSmoothScrollGesture : public SmoothScrollGesture {
private:
virtual ~BasicMouseWheelSmoothScrollGesture();
- SmoothScrollCalculator smooth_scroll_calculator_;
+ SyntheticGestureCalculator synthetic_gesture_calculator_;
bool scroll_down_;
int pixels_scrolled_;
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.cc b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
index 0e2426bf224..e681188b937 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
@@ -11,7 +11,6 @@
#include "content/public/browser/browser_context.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/zlib/zlib.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size.h"
#include "url/gurl.h"
@@ -199,19 +198,9 @@ void ClipboardMessageFilter::OnReadImageReply(
const SkBitmap& bitmap, IPC::Message* reply_msg) {
base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
uint32 image_size = 0;
- std::string reply_data;
if (!bitmap.isNull()) {
std::vector<unsigned char> png_data;
- SkAutoLockPixels lock(bitmap);
- if (gfx::PNGCodec::EncodeWithCompressionLevel(
- static_cast<const unsigned char*>(bitmap.getPixels()),
- gfx::PNGCodec::FORMAT_BGRA,
- gfx::Size(bitmap.width(), bitmap.height()),
- bitmap.rowBytes(),
- false,
- std::vector<gfx::PNGCodec::Comment>(),
- Z_BEST_SPEED,
- &png_data)) {
+ if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) {
base::SharedMemory buffer;
if (buffer.CreateAndMapAnonymous(png_data.size())) {
memcpy(buffer.memory(), vector_as_array(&png_data), png_data.size());
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
index 674e4e512d6..623272be771 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -19,7 +19,7 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "media/base/video_frame.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 53c42e4277a..1e758c35a0d 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -22,10 +22,13 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
+#include "cc/resources/scoped_ui_resource.h"
+#include "cc/resources/ui_resource_bitmap.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
@@ -37,6 +40,7 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/android/java_bitmap.h"
+#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace gfx {
@@ -48,8 +52,9 @@ namespace {
// Used for drawing directly to the screen. Bypasses resizing and swaps.
class DirectOutputSurface : public cc::OutputSurface {
public:
- DirectOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : cc::OutputSurface(context3d.Pass()) {
+ DirectOutputSurface(
+ const scoped_refptr<cc::ContextProvider>& context_provider)
+ : cc::OutputSurface(context_provider) {
capabilities_.adjust_deadline_for_parent = false;
}
@@ -57,23 +62,26 @@ class DirectOutputSurface : public cc::OutputSurface {
surface_size_ = size;
}
virtual void SwapBuffers(cc::CompositorFrame*) OVERRIDE {
- context3d()->shallowFlushCHROMIUM();
+ context_provider_->Context3d()->shallowFlushCHROMIUM();
}
};
// Used to override capabilities_.adjust_deadline_for_parent to false
class OutputSurfaceWithoutParent : public cc::OutputSurface {
public:
- OutputSurfaceWithoutParent(scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : cc::OutputSurface(context3d.Pass()) {
+ OutputSurfaceWithoutParent(
+ const scoped_refptr<
+ content::ContextProviderCommandBuffer>& context_provider)
+ : cc::OutputSurface(context_provider) {
capabilities_.adjust_deadline_for_parent = false;
}
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
- content::WebGraphicsContext3DCommandBufferImpl* command_buffer =
- static_cast<content::WebGraphicsContext3DCommandBufferImpl*>(context3d());
+ content::WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
+ static_cast<content::WebGraphicsContext3DCommandBufferImpl*>(
+ context_provider_->Context3d());
content::CommandBufferProxyImpl* command_buffer_proxy =
- command_buffer->GetCommandBufferProxy();
+ command_buffer_context->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
@@ -227,10 +235,11 @@ void CompositorImpl::SetSurface(jobject surface) {
void CompositorImpl::SetVisible(bool visible) {
if (!visible) {
+ ui_resource_map_.clear();
host_.reset();
+ client_->UIResourcesAreInvalid();
} else if (!host_) {
cc::LayerTreeSettings settings;
- settings.compositor_name = "BrowserCompositor";
settings.refresh_rate = 60.0;
settings.impl_side_painting = false;
settings.allow_antialiasing = false;
@@ -255,6 +264,9 @@ void CompositorImpl::SetVisible(bool visible) {
host_->SetLayerTreeHostClientReady();
host_->SetViewportSize(size_);
host_->set_has_transparent_background(has_transparent_background_);
+ // Need to recreate the UI resources because a new LayerTreeHost has been
+ // created.
+ client_->DidLoseUIResources();
}
}
@@ -286,6 +298,23 @@ bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
return false;
}
+cc::UIResourceId CompositorImpl::GenerateUIResource(
+ const cc::UIResourceBitmap& bitmap) {
+ if (!host_)
+ return 0;
+ scoped_ptr<cc::ScopedUIResource> ui_resource =
+ cc::ScopedUIResource::Create(host_.get(), bitmap);
+ cc::UIResourceId id = ui_resource->id();
+ ui_resource_map_.set(id, ui_resource.Pass());
+ return id;
+}
+
+void CompositorImpl::DeleteUIResource(cc::UIResourceId resource_id) {
+ UIResourceMap::iterator it = ui_resource_map_.find(resource_id);
+ if (it != ui_resource_map_.end())
+ ui_resource_map_.erase(it);
+}
+
WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
unsigned int texture_id = BuildBasicTexture();
WebKit::WebGraphicsContext3D* context =
@@ -358,6 +387,41 @@ bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
return true;
}
+static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
+CreateGpuProcessViewContext(
+ const WebKit::WebGraphicsContext3D::Attributes attributes,
+ int surface_id,
+ base::WeakPtr<CompositorImpl> compositor_impl) {
+ GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
+ GURL url("chrome://gpu/Compositor::createContext3D");
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
+ new WebGraphicsContext3DCommandBufferImpl(surface_id,
+ url,
+ factory,
+ compositor_impl));
+ static const size_t kBytesPerPixel = 4;
+ gfx::DeviceDisplayInfo display_info;
+ size_t full_screen_texture_size_in_bytes =
+ display_info.GetDisplayHeight() *
+ display_info.GetDisplayWidth() *
+ kBytesPerPixel;
+ if (!context->Initialize(
+ attributes,
+ false,
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
+ 64 * 1024, // command buffer size
+ 64 * 1024, // start transfer buffer size
+ 64 * 1024, // min transfer buffer size
+ std::min(3 * full_screen_texture_size_in_bytes,
+ kDefaultMaxTransferBufferSize),
+ 2 * 1024 * 1024 // mapped memory limit
+ )) {
+ LOG(ERROR) << "Failed to create 3D context for compositor.";
+ return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ }
+ return context.Pass();
+}
+
scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
bool fallback) {
WebKit::WebGraphicsContext3D::Attributes attrs;
@@ -365,46 +429,35 @@ scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
attrs.noAutomaticFlushes = true;
if (g_use_direct_gl) {
- scoped_ptr<WebKit::WebGraphicsContext3D> context(
- webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
- CreateViewContext(attrs, window_));
- if (!window_) {
- return scoped_ptr<cc::OutputSurface>(
- new DirectOutputSurface(context.Pass()));
- }
+ using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
+ scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d =
+ WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
+ attrs, window_);
+ scoped_refptr<webkit::gpu::ContextProviderInProcess> context_provider =
+ webkit::gpu::ContextProviderInProcess::Create(context3d.Pass(),
+ "BrowserCompositor");
+
+ scoped_ptr<cc::OutputSurface> output_surface;
+ if (!window_)
+ output_surface.reset(new DirectOutputSurface(context_provider));
+ else
+ output_surface.reset(new cc::OutputSurface(context_provider));
+ return output_surface.Pass();
+ }
- return make_scoped_ptr(new cc::OutputSurface(context.Pass()));
- } else {
- DCHECK(window_ && surface_id_);
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
- GURL url("chrome://gpu/Compositor::createContext3D");
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(surface_id_,
- url,
- factory,
- weak_factory_.GetWeakPtr()));
- static const size_t kBytesPerPixel = 4;
- gfx::DeviceDisplayInfo display_info;
- size_t full_screen_texture_size_in_bytes =
- display_info.GetDisplayHeight() *
- display_info.GetDisplayWidth() *
- kBytesPerPixel;
- if (!context->Initialize(
- attrs,
- false,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
- 64 * 1024, // command buffer size
- 64 * 1024, // start transfer buffer size
- 64 * 1024, // min transfer buffer size
- std::min(3 * full_screen_texture_size_in_bytes,
- kDefaultMaxTransferBufferSize))) {
- LOG(ERROR) << "Failed to create 3D context for compositor.";
- return scoped_ptr<cc::OutputSurface>();
- }
- return scoped_ptr<cc::OutputSurface>(
- new OutputSurfaceWithoutParent(
- context.PassAs<WebKit::WebGraphicsContext3D>()));
+ DCHECK(window_);
+ DCHECK(surface_id_);
+
+ scoped_refptr<ContextProviderCommandBuffer> context_provider =
+ ContextProviderCommandBuffer::Create(CreateGpuProcessViewContext(
+ attrs, surface_id_, weak_factory_.GetWeakPtr()), "BrowserCompositor");
+ if (!context_provider.get()) {
+ LOG(ERROR) << "Failed to create 3D context for compositor.";
+ return scoped_ptr<cc::OutputSurface>();
}
+
+ return scoped_ptr<cc::OutputSurface>(
+ new OutputSurfaceWithoutParent(context_provider));
}
void CompositorImpl::OnLostResources() {
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 845e830aad4..58e44c89449 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -7,8 +7,10 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "cc/resources/ui_resource_client.h"
#include "cc/trees/layer_tree_host_client.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/common/content_export.h"
@@ -21,6 +23,7 @@ namespace cc {
class InputHandlerClient;
class Layer;
class LayerTreeHost;
+class ScopedUIResource;
}
namespace content {
@@ -60,6 +63,9 @@ class CONTENT_EXPORT CompositorImpl
void *pixels, const gfx::Rect& rect) OVERRIDE;
virtual void SetNeedsRedraw() OVERRIDE;
virtual void Composite() OVERRIDE;
+ virtual cc::UIResourceId GenerateUIResource(
+ const cc::UIResourceBitmap& bitmap) OVERRIDE;
+ virtual void DeleteUIResource(cc::UIResourceId resource_id) OVERRIDE;
virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) OVERRIDE;
virtual WebKit::WebGLId GenerateCompressedTexture(
gfx::Size& size, int data_size, void* data) OVERRIDE;
@@ -117,6 +123,10 @@ class CONTENT_EXPORT CompositorImpl
scoped_refptr<cc::ContextProvider> null_offscreen_context_provider_;
+ typedef base::ScopedPtrHashMap<cc::UIResourceId, cc::ScopedUIResource>
+ UIResourceMap;
+ UIResourceMap ui_resource_map_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
};
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.cc b/chromium/content/browser/renderer_host/frame_memory_manager.cc
new file mode 100644
index 00000000000..708bddfa61b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_memory_manager.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/frame_memory_manager.h"
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/sys_info.h"
+
+namespace content {
+
+namespace {
+
+size_t MaxNumberOfSavedFrames() {
+ return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
+}
+
+} // namespace
+
+FrameMemoryManager* FrameMemoryManager::GetInstance() {
+ return Singleton<FrameMemoryManager>::get();
+}
+
+void FrameMemoryManager::AddFrame(FrameContainer* frame, bool visible) {
+ RemoveFrame(frame);
+ if (visible)
+ visible_frames_.insert(frame);
+ else
+ hidden_frames_.push_front(frame);
+ CullHiddenFrames();
+}
+
+void FrameMemoryManager::RemoveFrame(FrameContainer* frame) {
+ visible_frames_.erase(frame);
+ hidden_frames_.remove(frame);
+}
+
+void FrameMemoryManager::SetFrameVisibility(FrameContainer* frame,
+ bool visible) {
+ if (visible) {
+ hidden_frames_.remove(frame);
+ visible_frames_.insert(frame);
+ } else {
+ visible_frames_.erase(frame);
+ hidden_frames_.push_front(frame);
+ CullHiddenFrames();
+ }
+}
+
+FrameMemoryManager::FrameMemoryManager() {}
+
+FrameMemoryManager::~FrameMemoryManager() {}
+
+void FrameMemoryManager::CullHiddenFrames() {
+ while (!hidden_frames_.empty() &&
+ hidden_frames_.size() + visible_frames_.size() >
+ MaxNumberOfSavedFrames()) {
+ size_t old_size = hidden_frames_.size();
+ // Should remove self from list.
+ hidden_frames_.back()->ReleaseCurrentFrame();
+ DCHECK_EQ(hidden_frames_.size() + 1, old_size);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.h b/chromium/content/browser/renderer_host/frame_memory_manager.h
new file mode 100644
index 00000000000..ce3fc258226
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_memory_manager.h
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
+
+#include <list>
+#include <set>
+
+#include "base/basictypes.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+namespace content {
+
+class FrameContainer {
+ public:
+ virtual void ReleaseCurrentFrame() = 0;
+};
+
+class FrameMemoryManager {
+ public:
+ static FrameMemoryManager* GetInstance();
+
+ void AddFrame(FrameContainer*, bool visible);
+ void RemoveFrame(FrameContainer*);
+ void SetFrameVisibility(FrameContainer*, bool visible);
+
+ private:
+ FrameMemoryManager();
+ ~FrameMemoryManager();
+ void CullHiddenFrames();
+ friend struct DefaultSingletonTraits<FrameMemoryManager>;
+
+ std::set<FrameContainer*> visible_frames_;
+ std::list<FrameContainer*> hidden_frames_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameMemoryManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc b/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc
new file mode 100644
index 00000000000..74080cd408c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/generic_touch_gesture_android.h"
+
+#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "jni/GenericTouchGesture_jni.h"
+
+namespace {
+bool g_jni_initialized = false;
+
+void RegisterNativesIfNeeded(JNIEnv* env) {
+ if (!g_jni_initialized) {
+ content::RegisterNativesImpl(env);
+ g_jni_initialized = true;
+ }
+}
+} // namespace
+
+namespace content {
+
+GenericTouchGestureAndroid::GenericTouchGestureAndroid(
+ RenderWidgetHost* rwh,
+ base::android::ScopedJavaLocalRef<jobject> java_touch_gesture)
+ : has_started_(false),
+ has_finished_(false),
+ rwh_(rwh),
+ java_touch_gesture_(java_touch_gesture) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ RegisterNativesIfNeeded(env);
+}
+
+GenericTouchGestureAndroid::~GenericTouchGestureAndroid() {
+}
+
+bool GenericTouchGestureAndroid::ForwardInputEvents(
+ base::TimeTicks now, RenderWidgetHost* host) {
+ if (!has_started_) {
+ has_started_ = true;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_GenericTouchGesture_start(
+ env, java_touch_gesture_.obj(), reinterpret_cast<intptr_t>(this));
+ }
+
+ return !has_finished_;
+}
+
+float GenericTouchGestureAndroid::GetDelta(
+ JNIEnv* env, jobject obj, float scale) {
+ return synthetic_gesture_calculator_.GetDelta(
+ base::TimeTicks::Now(),
+ RenderWidgetHostImpl::From(rwh_)->GetSyntheticGestureMessageInterval()) *
+ scale;
+}
+
+void GenericTouchGestureAndroid::SetHasFinished(JNIEnv* env, jobject obj) {
+ has_finished_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/generic_touch_gesture_android.h b/chromium/content/browser/renderer_host/generic_touch_gesture_android.h
new file mode 100644
index 00000000000..030239b1c30
--- /dev/null
+++ b/chromium/content/browser/renderer_host/generic_touch_gesture_android.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
+
+#include "base/android/jni_android.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+#include "content/port/browser/synthetic_gesture.h"
+
+namespace content {
+
+class ContentViewCore;
+class RenderWidgetHost;
+
+class GenericTouchGestureAndroid : public SyntheticGesture {
+ public:
+ GenericTouchGestureAndroid(
+ RenderWidgetHost* rwh,
+ base::android::ScopedJavaLocalRef<jobject> java_scroller);
+
+ // Called by the java side once the TimeAnimator ticks.
+ float GetDelta(JNIEnv* env, jobject obj, float scale);
+ void SetHasFinished(JNIEnv* env, jobject obj);
+
+ // SmoothScrollGesture
+ virtual bool ForwardInputEvents(base::TimeTicks now,
+ RenderWidgetHost* host) OVERRIDE;
+
+ private:
+ virtual ~GenericTouchGestureAndroid();
+
+ SyntheticGestureCalculator synthetic_gesture_calculator_;
+
+ bool has_started_;
+ bool has_finished_;
+
+ RenderWidgetHost* rwh_;
+ base::android::ScopedJavaGlobalRef<jobject> java_touch_gesture_;
+
+ DISALLOW_COPY_AND_ASSIGN(GenericTouchGestureAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
index 55d2e76bb30..65dc54524c2 100644
--- a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -439,7 +439,7 @@ void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event,
// Unlike a Char event, an IME event is NOT dispatched to onkeypress()
// handlers or autofill.
host->ImeConfirmComposition(
- commit_text_,ui::Range::InvalidRange(),false);
+ commit_text_,gfx::Range::InvalidRange(),false);
// Set this flag to false, as this composition session has been
// finished.
is_composing_text_ = false;
@@ -477,7 +477,7 @@ void GtkIMContextWrapper::ConfirmComposition() {
if (host_view_->GetRenderWidgetHost()) {
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
}
// Reset the input method.
@@ -503,7 +503,7 @@ void GtkIMContextWrapper::HandleCommit(const string16& text) {
SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
- text, ui::Range::InvalidRange(), false);
+ text, gfx::Range::InvalidRange(), false);
SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
}
}
@@ -532,7 +532,7 @@ void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text,
// TODO(suzhe): due to a bug of webkit, we currently can't use selection range
// with composition string. See: https://bugs.webkit.org/show_bug.cgi?id=40805
- composition_.selection = ui::Range(cursor_position);
+ composition_.selection = gfx::Range(cursor_position);
// In case we are using a buggy input method which doesn't fire
// "preedit_start" signal.
diff --git a/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc b/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
index 93e20778607..861491111b5 100644
--- a/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
+++ b/chromium/content/browser/renderer_host/gtk_plugin_container_manager.cc
@@ -9,7 +9,7 @@
#include "base/logging.h"
#include "content/browser/renderer_host/gtk_plugin_container.h"
#include "content/common/webplugin_geometry.h"
-#include "ui/base/gtk/gtk_compat.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_util.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/gtk_window_utils.cc b/chromium/content/browser/renderer_host/gtk_window_utils.cc
index 979c58d05a5..f05cdca3b66 100644
--- a/chromium/content/browser/renderer_host/gtk_window_utils.cc
+++ b/chromium/content/browser/renderer_host/gtk_window_utils.cc
@@ -10,10 +10,11 @@
#include <vector>
-#include "ui/base/gtk/gtk_compat.h"
+#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/rect.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "ui/gfx/x/x11_types.h"
namespace content {
@@ -44,7 +45,7 @@ gfx::Rect GetWorkArea(Window window) {
property[start_index + 2], property[start_index + 3]);
}
-WebKit::WebScreenInfo GetScreenInfo(Display* display, int screenNumber) {
+WebKit::WebScreenInfo GetScreenInfo(XDisplay* display, int screenNumber) {
// XDisplayWidth() and XDisplayHeight() return cached values. To ensure that
// we return the correct dimensions after the screen is resized, query the
// root window's geometry each time.
diff --git a/chromium/content/browser/renderer_host/image_transport_factory_android.cc b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
index 39071c9bec3..bc0d365d249 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
@@ -128,7 +128,9 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
64 * 1024, // starting buffer size
64 * 1024, // min buffer size
std::min(3 * full_screen_texture_size_in_bytes,
- kDefaultMaxTransferBufferSize));
+ kDefaultMaxTransferBufferSize),
+ WebGraphicsContext3DCommandBufferImpl::kNoLimit
+ );
if (context_->makeContextCurrent())
context_->pushGroupMarkerEXT(
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index 588c5ada8e6..da14d7a3d5d 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -174,7 +174,7 @@ void ImeAdapterAndroid::CommitText(JNIEnv* env, jobject, jstring text) {
return;
string16 text16 = ConvertJavaStringToUTF16(env, text);
- rwhi->ImeConfirmComposition(text16, ui::Range::InvalidRange(), false);
+ rwhi->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
}
void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
@@ -182,7 +182,7 @@ void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
if (!rwhi)
return;
- rwhi->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), true);
+ rwhi->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), true);
}
void ImeAdapterAndroid::AttachImeAdapter(JNIEnv* env, jobject java_object) {
diff --git a/chromium/content/browser/renderer_host/input/OWNERS b/chromium/content/browser/renderer_host/input/OWNERS
index 4dabaf0da2c..4893edbdf02 100644
--- a/chromium/content/browser/renderer_host/input/OWNERS
+++ b/chromium/content/browser/renderer_host/input/OWNERS
@@ -1,2 +1,3 @@
-nduca@chromium.org
aelias@chromium.org
+jdduke@chromium.org
+nduca@chromium.org
diff --git a/chromium/content/browser/renderer_host/input/browser_input_event.cc b/chromium/content/browser/renderer_host/input/browser_input_event.cc
new file mode 100644
index 00000000000..276245e3526
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/browser_input_event.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/browser_input_event.h"
+
+#include "content/common/input/web_input_event_payload.h"
+
+namespace content {
+
+BrowserInputEvent::BrowserInputEvent(BrowserInputEventClient* client)
+ : client_(client) {}
+
+BrowserInputEvent::~BrowserInputEvent() {}
+
+scoped_ptr<BrowserInputEvent> BrowserInputEvent::Create(
+ int64 id,
+ scoped_ptr<InputEvent::Payload> payload,
+ BrowserInputEventClient* client) {
+ DCHECK(client);
+ scoped_ptr<BrowserInputEvent> event(new BrowserInputEvent(client));
+ event->Initialize(id, payload.Pass());
+ return event.Pass();
+}
+
+void BrowserInputEvent::OnDispatched(
+ InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup_events) {
+ DCHECK(followup_events);
+
+ bool event_consumed =
+ disposition == INPUT_EVENT_MAIN_THREAD_CONSUMED ||
+ disposition == INPUT_EVENT_IMPL_THREAD_CONSUMED ||
+ disposition == INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED;
+
+ if (!event_consumed && CanCreateFollowupEvents())
+ client_->OnDispatched(*this, disposition, followup_events);
+ else
+ client_->OnDispatched(*this, disposition);
+}
+
+bool BrowserInputEvent::CanCreateFollowupEvents() const {
+ return payload()->GetType() == InputEvent::Payload::WEB_INPUT_EVENT &&
+ WebInputEventPayload::Cast(payload())->CanCreateFollowupEvents();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/browser_input_event.h b/chromium/content/browser/renderer_host/input/browser_input_event.h
new file mode 100644
index 00000000000..6022d80ecd2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/browser_input_event.h
@@ -0,0 +1,69 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "content/common/input/input_event.h"
+#include "content/common/input/input_event_disposition.h"
+
+namespace content {
+
+class BrowserInputEvent;
+
+// Provides customized dispatch response for BrowserInputEvents.
+class BrowserInputEventClient {
+ public:
+ virtual ~BrowserInputEventClient() {}
+
+ virtual void OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition) {}
+
+ // Called if the event went unconsumed and can create followup events. Any
+ // events added to |followup| by the client will be inserted into the
+ // current input event stream. |followup| will never be NULL.
+ virtual void OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup) {}
+};
+
+// Augmented InputEvent allowing customized dispatch response in the browser.
+class CONTENT_EXPORT BrowserInputEvent : public InputEvent {
+ public:
+ // |client| is assumed to be non-NULL.
+ static scoped_ptr<BrowserInputEvent> Create(
+ int64 id,
+ scoped_ptr<InputEvent::Payload> payload,
+ BrowserInputEventClient* client);
+
+ template <typename PayloadType>
+ static scoped_ptr<BrowserInputEvent> Create(int64 id,
+ scoped_ptr<PayloadType> payload,
+ BrowserInputEventClient* client) {
+ return Create(id, payload.template PassAs<InputEvent::Payload>(), client);
+ }
+
+ virtual ~BrowserInputEvent();
+
+ // |followup_events| must not be NULL, and will only be modified if the
+ // event went unconsumed and can create followup events.
+ void OnDispatched(InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup_events);
+
+ protected:
+ explicit BrowserInputEvent(BrowserInputEventClient* client);
+
+ bool CanCreateFollowupEvents() const;
+
+ private:
+ BrowserInputEventClient* client_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router.cc b/chromium/content/browser/renderer_host/input/buffered_input_router.cc
new file mode 100644
index 00000000000..97b565311d5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router.cc
@@ -0,0 +1,336 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/buffered_input_router.h"
+
+#include "base/auto_reset.h"
+#include "content/browser/renderer_host/input/browser_input_event.h"
+#include "content/browser/renderer_host/input/input_ack_handler.h"
+#include "content/browser/renderer_host/input/input_queue.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/browser/user_metrics.h"
+
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+
+namespace content {
+
+BufferedInputRouter::BufferedInputRouter(IPC::Sender* sender,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id)
+ : client_(client),
+ ack_handler_(ack_handler),
+ sender_(sender),
+ routing_id_(routing_id),
+ has_touch_handler_(false),
+ queued_touch_count_(0),
+ input_queue_override_(NULL),
+ next_input_id_(1),
+ in_flight_packet_id_(0) {
+ input_queue_.reset(new InputQueue(this));
+}
+
+BufferedInputRouter::~BufferedInputRouter() {}
+
+void BufferedInputRouter::Flush() {
+ TRACE_EVENT0("input", "BufferedInputRouter::Flush");
+ DCHECK_EQ(0, in_flight_packet_id_);
+ input_queue_->BeginFlush();
+}
+
+bool BufferedInputRouter::SendInput(scoped_ptr<IPC::Message> message) {
+ DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
+ DCHECK(message->type() != InputMsg_HandleEventPacket::ID);
+ DCHECK(message->type() != InputMsg_HandleInputEvent::ID);
+ input_queue_->QueueEvent(BrowserInputEvent::Create(
+ NextInputID(), IPCInputEventPayload::Create(message.Pass()), this));
+ return true;
+}
+
+void BufferedInputRouter::SendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ if (!client_->OnSendMouseEvent(mouse_event))
+ return;
+ // TODO(jdduke): Coalescing, http://crbug.com/289520
+ QueueWebEvent(mouse_event.event, mouse_event.latency, false);
+}
+
+void BufferedInputRouter::SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ if (!client_->OnSendWheelEvent(wheel_event))
+ return;
+ QueueWebEvent(wheel_event.event, wheel_event.latency, false);
+}
+
+void BufferedInputRouter::SendKeyboardEvent(
+ const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) {
+ bool is_shortcut = false;
+ if (!client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut))
+ return;
+ int64 event_id = QueueWebEvent(key_event, latency_info, is_shortcut);
+ if (event_id) {
+ DCHECK(queued_key_map_.find(event_id) == queued_key_map_.end());
+ queued_key_map_[event_id] = key_event;
+ }
+}
+
+void BufferedInputRouter::SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ if (!client_->OnSendGestureEvent(gesture_event))
+ return;
+ QueueWebEvent(gesture_event.event, gesture_event.latency, false);
+}
+
+void BufferedInputRouter::SendTouchEvent(
+ const TouchEventWithLatencyInfo& touch_event) {
+ if (!client_->OnSendTouchEvent(touch_event))
+ return;
+ if (QueueWebEvent(touch_event.event, touch_event.latency, false))
+ ++queued_touch_count_;
+}
+
+void BufferedInputRouter::SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ if (!client_->OnSendMouseEventImmediately(mouse_event))
+ return;
+ QueueWebEvent(mouse_event.event, mouse_event.latency, false);
+}
+
+void BufferedInputRouter::SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) {
+ if (!client_->OnSendTouchEventImmediately(touch_event))
+ return;
+ QueueWebEvent(touch_event.event, touch_event.latency, false);
+}
+
+void BufferedInputRouter::SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ if (!client_->OnSendGestureEventImmediately(gesture_event))
+ return;
+ QueueWebEvent(gesture_event.event, gesture_event.latency, false);
+}
+
+void BufferedInputRouter::Deliver(const EventPacket& packet) {
+ TRACE_EVENT2("input", "BufferedInputRouter::DeliverPacket",
+ "id", packet.id(),
+ "events", packet.size());
+ DCHECK(packet.id());
+ DCHECK(!in_flight_packet_id_);
+ if (!sender_->Send(new InputMsg_HandleEventPacket(
+ routing_id_, packet, InputEventDispositions()))) {
+ return;
+ }
+
+ in_flight_packet_id_ = packet.id();
+ client_->IncrementInFlightEventCount();
+}
+
+void BufferedInputRouter::DidFinishFlush() {
+ TRACE_EVENT0("input", "BufferedInputRouter::DidFinishFlush");
+ client_->DidFlush();
+}
+
+void BufferedInputRouter::SetNeedsFlush() {
+ TRACE_EVENT0("input", "BufferedInputRouter::SetNeedsFlush");
+ client_->SetNeedsFlush();
+}
+
+void BufferedInputRouter::OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition) {
+ // Only WebInputEvents currently have ack response.
+ if (event.payload()->GetType() != InputEvent::Payload::WEB_INPUT_EVENT)
+ return;
+
+ const WebInputEventPayload* web_payload =
+ WebInputEventPayload::Cast(event.payload());
+
+ OnWebInputEventAck(event.id(),
+ *web_payload->web_event(),
+ web_payload->latency_info(),
+ ToAckState(disposition),
+ true);
+}
+
+void BufferedInputRouter::OnDispatched(
+ const BrowserInputEvent& event,
+ InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup) {
+ DCHECK(followup);
+ DCHECK_NE(INPUT_EVENT_ACK_STATE_CONSUMED, ToAckState(disposition));
+
+ // Events sent to the router within this scope will be added to |followup|.
+ base::AutoReset<ScopedVector<BrowserInputEvent>*> input_queue_override(
+ &input_queue_override_, followup);
+
+ OnDispatched(event, disposition);
+}
+
+bool BufferedInputRouter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ bool message_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(BufferedInputRouter, message, message_is_ok)
+ IPC_MESSAGE_HANDLER(InputHostMsg_HandleEventPacket_ACK, OnEventPacketAck)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
+ OnHasTouchEventHandlers)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ if (!message_is_ok)
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
+
+ return handled;
+}
+
+const NativeWebKeyboardEvent*
+ BufferedInputRouter::GetLastKeyboardEvent() const {
+ return queued_key_map_.empty() ? NULL : &queued_key_map_.begin()->second;
+}
+
+bool BufferedInputRouter::ShouldForwardTouchEvent() const {
+ return has_touch_handler_ && queued_touch_count_ > 0;
+}
+
+bool BufferedInputRouter::ShouldForwardGestureEvent(
+ const GestureEventWithLatencyInfo& touch_event) const {
+ return true;
+}
+
+void BufferedInputRouter::OnWebInputEventAck(
+ int64 event_id,
+ const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ InputEventAckState acked_result,
+ bool ack_from_input_queue) {
+ if (WebInputEvent::isKeyboardEventType(web_event.type)) {
+ if (ack_from_input_queue) {
+ KeyMap::iterator key_it = queued_key_map_.find(event_id);
+ DCHECK(key_it != queued_key_map_.end());
+ NativeWebKeyboardEvent key_event = key_it->second;
+ queued_key_map_.erase(key_it);
+ ack_handler_->OnKeyboardEventAck(key_event, acked_result);
+ } else {
+ DCHECK_EQ(0, event_id);
+ ack_handler_->OnKeyboardEventAck(
+ static_cast<const NativeWebKeyboardEvent&>(web_event), acked_result);
+ }
+ // WARNING: This BufferedInputRouter can be deallocated at this point
+ // (i.e. in the case of Ctrl+W, where the call to
+ // HandleKeyboardEvent destroys this BufferedInputRouter).
+ } else if (web_event.type == WebInputEvent::MouseWheel) {
+ ack_handler_->OnWheelEventAck(
+ static_cast<const WebMouseWheelEvent&>(web_event), acked_result);
+ } else if (WebInputEvent::isTouchEventType(web_event.type)) {
+ if (ack_from_input_queue) {
+ DCHECK_GT(queued_touch_count_, 0);
+ --queued_touch_count_;
+ }
+ ack_handler_->OnTouchEventAck(
+ TouchEventWithLatencyInfo(static_cast<const WebTouchEvent&>(web_event),
+ latency_info),
+ acked_result);
+ } else if (WebInputEvent::isGestureEventType(web_event.type)) {
+ ack_handler_->OnGestureEventAck(
+ static_cast<const WebGestureEvent&>(web_event), acked_result);
+ } else
+ NOTREACHED() << "Unexpected WebInputEvent in OnWebInputEventAck";
+}
+
+void BufferedInputRouter::OnEventPacketAck(
+ int64 packet_id,
+ const InputEventDispositions& dispositions) {
+ TRACE_EVENT2("input", "BufferedInputRouter::OnEventPacketAck",
+ "id", packet_id,
+ "dispositions", dispositions.size());
+ if (!in_flight_packet_id_ || packet_id != in_flight_packet_id_) {
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
+ return;
+ }
+
+ in_flight_packet_id_ = 0;
+ client_->DecrementInFlightEventCount();
+
+ InputQueue::AckResult ack_result =
+ input_queue_->OnEventPacketAck(packet_id, dispositions);
+ if (ack_result == InputQueue::ACK_UNEXPECTED)
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
+ else if (ack_result == InputQueue::ACK_INVALID)
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
+}
+
+void BufferedInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
+ if (has_touch_handler_ == has_handlers)
+ return;
+ has_touch_handler_ = has_handlers;
+ client_->OnHasTouchEventHandlers(has_handlers);
+}
+
+int64 BufferedInputRouter::QueueWebEvent(const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_key_shortcut) {
+ TRACE_EVENT0("input", "BufferedInputRouter::QueueWebEvent");
+
+ if (FilterWebEvent(web_event, latency_info)) {
+ TRACE_EVENT_INSTANT0("input",
+ "BufferedInputRouter::QueueWebEvent::Filtered",
+ TRACE_EVENT_SCOPE_THREAD);
+ return 0;
+ }
+
+ int64 event_id = NextInputID();
+ scoped_ptr<BrowserInputEvent> event = BrowserInputEvent::Create(
+ event_id,
+ WebInputEventPayload::Create(web_event,
+ latency_info,
+ is_key_shortcut),
+ this);
+
+ // The presence of |input_queue_override_| implies that we are in the
+ // scope of |OnInputEventDispatched()| with an event can create followup.
+ if (input_queue_override_)
+ input_queue_override_->push_back(event.release());
+ else
+ input_queue_->QueueEvent(event.Pass());
+
+ return event_id;
+}
+
+bool BufferedInputRouter::FilterWebEvent(const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info) {
+ // Perform optional, synchronous event handling, sending ACK messages for
+ // processed events, or proceeding as usual.
+ InputEventAckState filter_ack =
+ client_->FilterInputEvent(web_event, latency_info);
+ switch (filter_ack) {
+ // Send the ACK and early exit.
+ case INPUT_EVENT_ACK_STATE_CONSUMED:
+ case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
+ OnWebInputEventAck(0, web_event, latency_info, filter_ack, false);
+ // WARNING: |this| may be deleted at this point.
+ return true;
+
+ // Drop the event.
+ case INPUT_EVENT_ACK_STATE_UNKNOWN:
+ return true;
+
+ // Proceed as normal.
+ case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
+ default:
+ break;
+ };
+
+ return false;
+}
+
+int64 BufferedInputRouter::NextInputID() { return next_input_id_++; }
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router.h b/chromium/content/browser/renderer_host/input/buffered_input_router.h
new file mode 100644
index 00000000000..a9802a68198
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router.h
@@ -0,0 +1,144 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
+#define CONTENT_BROWSER_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "content/browser/renderer_host/input/browser_input_event.h"
+#include "content/browser/renderer_host/input/input_queue.h"
+#include "content/browser/renderer_host/input/input_queue_client.h"
+#include "content/browser/renderer_host/input/input_router.h"
+
+namespace IPC {
+class Sender;
+}
+
+namespace content {
+
+class InputAckHandler;
+class RenderProcessHost;
+class RenderWidgetHostImpl;
+
+// Batches input events into EventPackets using a general input queue. Packets
+// are sent the renderer on |Flush()|, called in response to flush requests.
+class CONTENT_EXPORT BufferedInputRouter
+ : public NON_EXPORTED_BASE(BrowserInputEventClient),
+ public NON_EXPORTED_BASE(InputQueueClient),
+ public NON_EXPORTED_BASE(InputRouter) {
+ public:
+ // |sender|, |client| and |ack_handler| must outlive the BufferedInputRouter.
+ BufferedInputRouter(IPC::Sender* sender,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id);
+ virtual ~BufferedInputRouter();
+
+ // InputRouter
+ virtual void Flush() OVERRIDE;
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE;
+
+ // Certain unhandled input event acks may create follow-up events, e.g.,
+ // TouchEvent -> GestureEvent. If these follow-up events are sent to the
+ // router synchronously from the original event's |OnDispatched()| ack, they
+ // will be inserted into the current input flush stream.
+ virtual void SendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
+ virtual void SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
+ virtual void SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual void SendTouchEvent(
+ const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
+ virtual void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
+ virtual void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
+ virtual void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
+ virtual bool ShouldForwardTouchEvent() const OVERRIDE;
+ virtual bool ShouldForwardGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE;
+
+ // InputQueueClient
+ virtual void Deliver(const EventPacket& packet) OVERRIDE;
+ virtual void DidFinishFlush() OVERRIDE;
+ virtual void SetNeedsFlush() OVERRIDE;
+
+ // BrowserInputEventClient
+ virtual void OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition) OVERRIDE;
+ // Events delivered to the router within the scope of
+ // |OnDispatched()| will be added to |followup|.
+ virtual void OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup) OVERRIDE;
+
+ // IPC::Receiver
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ protected:
+ void OnWebInputEventAck(int64 event_id,
+ const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ InputEventAckState acked_result,
+ bool ack_from_input_queue);
+ void OnEventPacketAck(int64 packet_id,
+ const InputEventDispositions& dispositions);
+ void OnHasTouchEventHandlers(bool has_handlers);
+
+ // Returns the non-zero ID associated with the |InputEvent| added to the
+ // |input_queue_|. If the event was dropped or filtered, returns 0.
+ int64 QueueWebEvent(const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_key_shortcut);
+ // Used by |QueueWebEvent()|; returns true if an event was filtered and should
+ // not be added to the |input_queue_|.
+ bool FilterWebEvent(const WebKit::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info);
+
+ // Generates a monotonically increasing sequences of id's, starting with 1.
+ int64 NextInputID();
+
+ const InputQueue* input_queue() const { return input_queue_.get(); }
+
+ private:
+ InputRouterClient* client_;
+ InputAckHandler* ack_handler_;
+ IPC::Sender* sender_;
+ int routing_id_;
+
+ scoped_ptr<InputQueue> input_queue_;
+
+ // TODO(jdduke): Remove when we can properly serialize NativeWebKeyboardEvent.
+ // Alternatively, attach WebInputEvents to InputEvents but don't serialize.
+ typedef std::map<int64, NativeWebKeyboardEvent> KeyMap;
+ KeyMap queued_key_map_;
+
+ // Necessary for |ShouldForwardTouchEvent()|.
+ bool has_touch_handler_;
+ int queued_touch_count_;
+
+ // This is non-NULL ONLY in the scope of OnInputEventAck(event, injector).
+ ScopedVector<BrowserInputEvent>* input_queue_override_;
+
+ // Used to assign unique ID's to each InputEvent that is generated.
+ int64 next_input_id_;
+
+ // 0 if there no in-flight EventPacket.
+ int64 in_flight_packet_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferedInputRouter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc b/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc
new file mode 100644
index 00000000000..4d63444fef8
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc
@@ -0,0 +1,320 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "content/browser/renderer_host/input/buffered_input_router.h"
+#include "content/browser/renderer_host/input/input_router_unittest.h"
+#include "content/common/input/event_packet.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+using WebKit::WebTouchPoint;
+
+namespace content {
+
+class TestBufferedInputRouter : public BufferedInputRouter {
+ public:
+ TestBufferedInputRouter(IPC::Sender* sender,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id)
+ : BufferedInputRouter(sender, client, ack_handler, routing_id) {}
+
+
+ size_t QueuedEventCount() const { return input_queue()->QueuedEventCount(); }
+};
+
+class BufferedInputRouterTest : public InputRouterTest {
+ public:
+ BufferedInputRouterTest() {}
+ virtual ~BufferedInputRouterTest() {}
+
+ protected:
+ // InputRouterTest
+ virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
+ InputRouterClient* client,
+ InputAckHandler* handler,
+ int routing_id) OVERRIDE {
+ return scoped_ptr<InputRouter>(
+ new TestBufferedInputRouter(process, client, handler, routing_id));
+ }
+
+ bool FinishFlush(const InputEventDispositions& dispositions) {
+ if (!process_->sink().message_count())
+ return false;
+ IPC::Message message(*process_->sink().GetMessageAt(0));
+ process_->sink().ClearMessages();
+
+ InputMsg_HandleEventPacket::Param param;
+ InputMsg_HandleEventPacket::Read(&message, &param);
+ EventPacket& packet = param.a;
+
+ return SendEventPacketACK(packet.id(), dispositions);
+ }
+
+ bool FinishFlush(InputEventDisposition disposition) {
+ if (!process_->sink().message_count())
+ return false;
+ IPC::Message message(*process_->sink().GetMessageAt(0));
+ process_->sink().ClearMessages();
+
+ InputMsg_HandleEventPacket::Param param;
+ InputMsg_HandleEventPacket::Read(&message, &param);
+ EventPacket& packet = param.a;
+
+ return SendEventPacketACK(
+ packet.id(), InputEventDispositions(packet.size(), disposition));
+ }
+
+ bool SendEventPacketACK(int id, const InputEventDispositions& dispositions) {
+ return input_router_->OnMessageReceived(
+ InputHostMsg_HandleEventPacket_ACK(0, id, dispositions));
+ }
+
+ size_t QueuedEventCount() const {
+ return buffered_input_router()->QueuedEventCount();
+ }
+
+ TestBufferedInputRouter* buffered_input_router() const {
+ return static_cast<TestBufferedInputRouter*>(input_router_.get());
+ }
+};
+
+TEST_F(BufferedInputRouterTest, InputEventsProperlyQueued) {
+ EXPECT_TRUE(input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_Redo(MSG_ROUTING_NONE))));
+ EXPECT_EQ(1U, QueuedEventCount());
+
+ EXPECT_TRUE(input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_Cut(MSG_ROUTING_NONE))));
+ EXPECT_EQ(2U, QueuedEventCount());
+
+ EXPECT_TRUE(input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_Copy(MSG_ROUTING_NONE))));
+ EXPECT_EQ(3U, QueuedEventCount());
+
+ EXPECT_TRUE(input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_Paste(MSG_ROUTING_NONE))));
+ EXPECT_EQ(4U, QueuedEventCount());
+}
+
+#define SCOPED_EXPECT(CALL, MESSAGE) { SCOPED_TRACE(MESSAGE); CALL; }
+
+TEST_F(BufferedInputRouterTest, ClientOnSendEventCalled) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(1U, QueuedEventCount());
+
+ SimulateWheelEvent(5, 0, 0, false);
+ EXPECT_EQ(2U, QueuedEventCount());
+
+ SimulateMouseMove(5, 0, 0);
+ EXPECT_EQ(3U, QueuedEventCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchpad);
+ EXPECT_EQ(4U, QueuedEventCount());
+
+ SimulateTouchEvent(1, 1);
+ EXPECT_EQ(5U, QueuedEventCount());
+}
+
+TEST_F(BufferedInputRouterTest, ClientOnSendEventHonored) {
+ client_->set_allow_send_event(false);
+
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(0U, QueuedEventCount());
+
+ SimulateWheelEvent(5, 0, 0, false);
+ EXPECT_EQ(0U, QueuedEventCount());
+
+ SimulateMouseMove(5, 0, 0);
+ EXPECT_EQ(0U, QueuedEventCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchpad);
+ EXPECT_EQ(0U, QueuedEventCount());
+
+ SimulateTouchEvent(1, 1);
+ EXPECT_EQ(0U, QueuedEventCount());
+}
+
+TEST_F(BufferedInputRouterTest, FlightCountIncrementedOnDeliver) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ input_router_->Flush();
+ EXPECT_EQ(1, client_->in_flight_event_count());
+}
+
+TEST_F(BufferedInputRouterTest, FlightCountDecrementedOnAck) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ input_router_->Flush();
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // The in-flight count should continue until the flush has finished.
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER));
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+TEST_F(BufferedInputRouterTest, FilteredEventsNeverQueued) {
+ // Event should not be queued, but should be ack'ed.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
+ EXPECT_EQ(0U, QueuedEventCount());
+ ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+
+ // Event should not be queued, but should be ack'ed.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
+ EXPECT_EQ(0U, QueuedEventCount());
+ ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+
+ // |INPUT_EVENT_DISPOSITION_UNKNOWN| should drop the event without ack'ing.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
+ EXPECT_EQ(0U, QueuedEventCount());
+ ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+
+ // Event should be queued.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
+ EXPECT_EQ(1U, QueuedEventCount());
+}
+
+TEST_F(BufferedInputRouterTest, FollowupEventsInjected) {
+ // Enable a followup gesture event.
+ WebGestureEvent followup_event;
+ followup_event.type = WebInputEvent::GestureScrollBegin;
+ followup_event.data.scrollUpdate.deltaX = 10;
+ ack_handler_->set_followup_touch_event(make_scoped_ptr(
+ new GestureEventWithLatencyInfo(followup_event, ui::LatencyInfo())));
+
+ // Create an initial packet of { Touch, Key } and start flushing.
+ SimulateTouchEvent(1, 1);
+ EXPECT_EQ(1U, QueuedEventCount());
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(2U, QueuedEventCount());
+ input_router_->Flush();
+
+ // Followup only triggered when event handled.
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER));
+ SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
+ EXPECT_EQ(2U, QueuedEventCount());
+
+ // Ack the touch event.
+ InputEventDispositions dispositions;
+ dispositions.push_back(INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED);
+ dispositions.push_back(INPUT_EVENT_COULD_NOT_DELIVER);
+ ASSERT_TRUE(FinishFlush(dispositions));
+
+ // Ack'ing the touch event should have inserted the followup gesture event;
+ // the flush is not complete until the inserted event is ack'ed.
+ SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
+ SCOPED_EXPECT(client_->ExpectSendCalled(true), "SendGestureCalled");
+ EXPECT_EQ(followup_event.type, client_->sent_gesture_event().event.type);
+ EXPECT_EQ(2U, QueuedEventCount());
+
+ // Our packet is now { Gesture, Key }.
+ InputMsg_HandleEventPacket::Param param;
+ ASSERT_EQ(1U, process_->sink().message_count());
+ ASSERT_TRUE(InputMsg_HandleEventPacket::Read(process_->sink().GetMessageAt(0),
+ &param));
+ EventPacket& followup_packet = param.a;
+ ASSERT_EQ(2U, followup_packet.size());
+ ASSERT_EQ(InputEvent::Payload::WEB_INPUT_EVENT,
+ followup_packet.events()[0]->payload()->GetType());
+ ASSERT_EQ(InputEvent::Payload::WEB_INPUT_EVENT,
+ followup_packet.events()[1]->payload()->GetType());
+ const WebInputEventPayload* payload0 =
+ WebInputEventPayload::Cast(followup_packet.events()[0]->payload());
+ const WebInputEventPayload* payload1 =
+ WebInputEventPayload::Cast(followup_packet.events()[1]->payload());
+ EXPECT_EQ(followup_event.type, payload0->web_event()->type);
+ EXPECT_EQ(WebInputEvent::RawKeyDown, payload1->web_event()->type);
+
+ // Complete the flush; the gesture should have been ack'ed.
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
+ SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
+ EXPECT_EQ(followup_event.type, ack_handler_->acked_gesture_event().type);
+ EXPECT_EQ(0U, QueuedEventCount());
+}
+
+TEST_F(BufferedInputRouterTest, FlushRequestedOnQueue) {
+ // The first queued event should trigger a flush request.
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(1U, QueuedEventCount());
+ SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(true), "SetNeedsFlushCalled");
+
+ // Subsequently queued events will not trigger another flush request.
+ SimulateWheelEvent(5, 0, 0, false);
+ EXPECT_EQ(2U, QueuedEventCount());
+ SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(false), "SetNeedsFlushCalled");
+}
+
+TEST_F(BufferedInputRouterTest, GetLastKeyboardEvent) {
+ EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ input_router_->GetLastKeyboardEvent()->type);
+
+ // Queueing another key event does not effect the "last" event.
+ SimulateKeyboardEvent(WebInputEvent::KeyUp);
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ input_router_->GetLastKeyboardEvent()->type);
+
+ input_router_->Flush();
+
+ // Ack'ing the first event should make the second event the "last" event.
+ InputEventDispositions dispositions;
+ dispositions.push_back(INPUT_EVENT_IMPL_THREAD_CONSUMED);
+ dispositions.push_back(INPUT_EVENT_COULD_NOT_DELIVER);
+ ASSERT_TRUE(FinishFlush(dispositions));
+ EXPECT_EQ(WebInputEvent::KeyUp, input_router_->GetLastKeyboardEvent()->type);
+
+ // A key event queued during a flush becomes "last" upon flush completion.
+ SimulateKeyboardEvent(WebInputEvent::Char);
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
+ EXPECT_EQ(WebInputEvent::Char, input_router_->GetLastKeyboardEvent()->type);
+
+ // An empty queue should produce a null "last" event.
+ input_router_->Flush();
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
+ EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+}
+
+TEST_F(BufferedInputRouterTest, UnexpectedAck) {
+ ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
+ input_router_->OnMessageReceived(
+ InputHostMsg_HandleEventPacket_ACK(0, 0, InputEventDispositions()));
+ EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
+}
+
+TEST_F(BufferedInputRouterTest, BadAck) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
+ input_router_->Flush();
+
+ ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
+ EventPacket packet;
+ input_router_->OnMessageReceived(
+ InputHostMsg_HandleEventPacket_ACK(0, 0, InputEventDispositions()));
+ EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router.cc b/chromium/content/browser/renderer_host/input/immediate_input_router.cc
index 96e8bb9ac44..a4c69054fd1 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.cc
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "content/browser/renderer_host/input/gesture_event_filter.h"
+#include "content/browser/renderer_host/input/input_ack_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
@@ -20,8 +21,8 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
-#include "ui/base/events/event.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
using base::Time;
using base::TimeDelta;
@@ -71,12 +72,13 @@ const char* GetEventAckName(InputEventAckState ack_result) {
} // namespace
-ImmediateInputRouter::ImmediateInputRouter(
- RenderProcessHost* process,
- InputRouterClient* client,
- int routing_id)
+ImmediateInputRouter::ImmediateInputRouter(RenderProcessHost* process,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id)
: process_(process),
client_(client),
+ ack_handler_(ack_handler),
routing_id_(routing_id),
select_range_pending_(false),
move_caret_pending_(false),
@@ -85,6 +87,9 @@ ImmediateInputRouter::ImmediateInputRouter(
has_touch_handler_(false),
touch_event_queue_(new TouchEventQueue(this)),
gesture_event_filter_(new GestureEventFilter(this)) {
+ enable_no_touch_to_renderer_while_scrolling_ =
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNoTouchToRendererWhileScrolling);
DCHECK(process);
DCHECK(client);
}
@@ -92,20 +97,23 @@ ImmediateInputRouter::ImmediateInputRouter(
ImmediateInputRouter::~ImmediateInputRouter() {
}
-bool ImmediateInputRouter::SendInput(IPC::Message* message) {
+void ImmediateInputRouter::Flush() {
+ NOTREACHED() << "ImmediateInputRouter will never request a flush.";
+}
+
+bool ImmediateInputRouter::SendInput(scoped_ptr<IPC::Message> message) {
DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
- scoped_ptr<IPC::Message> scoped_message(message);
- switch (scoped_message->type()) {
+ switch (message->type()) {
// Check for types that require an ACK.
case InputMsg_SelectRange::ID:
- return SendSelectRange(scoped_message.release());
+ return SendSelectRange(message.Pass());
case InputMsg_MoveCaret::ID:
- return SendMoveCaret(scoped_message.release());
+ return SendMoveCaret(message.Pass());
case InputMsg_HandleInputEvent::ID:
NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
return false;
default:
- return Send(scoped_message.release());
+ return Send(message.release());
}
}
@@ -199,6 +207,7 @@ void ImmediateInputRouter::SendKeyboardEvent(
void ImmediateInputRouter::SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) {
+ HandleGestureScroll(gesture_event);
if (!client_->OnSendGestureEvent(gesture_event))
return;
FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
@@ -252,6 +261,7 @@ void ImmediateInputRouter::SendTouchEventImmediately(
void ImmediateInputRouter::SendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) {
+ HandleGestureScroll(gesture_event);
if (!client_->OnSendGestureEventImmediately(gesture_event))
return;
FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
@@ -277,10 +287,6 @@ bool ImmediateInputRouter::ShouldForwardGestureEvent(
return gesture_event_filter_->ShouldForward(touch_event);
}
-bool ImmediateInputRouter::HasQueuedGestureEvents() const {
- return gesture_event_filter_->HasQueuedGestureEvents();
-}
-
bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
bool message_is_ok = true;
@@ -294,7 +300,7 @@ bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
IPC_END_MESSAGE_MAP()
if (!message_is_ok)
- client_->OnUnexpectedEventAck(true);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
return handled;
}
@@ -302,29 +308,29 @@ bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
void ImmediateInputRouter::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- client_->OnTouchEventAck(event, ack_result);
+ ack_handler_->OnTouchEventAck(event, ack_result);
}
-bool ImmediateInputRouter::SendSelectRange(IPC::Message* message) {
+bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) {
DCHECK(message->type() == InputMsg_SelectRange::ID);
if (select_range_pending_) {
- next_selection_range_.reset(message);
+ next_selection_range_ = message.Pass();
return true;
}
select_range_pending_ = true;
- return Send(message);
+ return Send(message.release());
}
-bool ImmediateInputRouter::SendMoveCaret(IPC::Message* message) {
+bool ImmediateInputRouter::SendMoveCaret(scoped_ptr<IPC::Message> message) {
DCHECK(message->type() == InputMsg_MoveCaret::ID);
if (move_caret_pending_) {
- next_move_caret_.reset(message);
+ next_move_caret_ = message.Pass();
return true;
}
move_caret_pending_ = true;
- return Send(message);
+ return Send(message.release());
}
bool ImmediateInputRouter::Send(IPC::Message* message) {
@@ -398,7 +404,7 @@ void ImmediateInputRouter::FilterAndSendWebInputEvent(
// Proceed as normal.
case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
break;
- };
+ }
// Transmit any pending wheel events on a non-wheel event. This ensures that
// the renderer receives the final PhaseEnded wheel event, which is necessary
@@ -434,13 +440,13 @@ void ImmediateInputRouter::OnInputEventAck(
void ImmediateInputRouter::OnMsgMoveCaretAck() {
move_caret_pending_ = false;
if (next_move_caret_)
- SendMoveCaret(next_move_caret_.release());
+ SendMoveCaret(next_move_caret_.Pass());
}
void ImmediateInputRouter::OnSelectRangeAck() {
select_range_pending_ = false;
if (next_selection_range_)
- SendSelectRange(next_selection_range_.release());
+ SendSelectRange(next_selection_range_.Pass());
}
void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
@@ -461,7 +467,7 @@ void ImmediateInputRouter::ProcessInputEventAck(
int type = static_cast<int>(event_type);
if (type < WebInputEvent::Undefined) {
- client_->OnUnexpectedEventAck(true);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
} else if (type == WebInputEvent::MouseMove) {
mouse_move_pending_ = false;
@@ -501,23 +507,17 @@ void ImmediateInputRouter::ProcessKeyboardAck(
int type,
InputEventAckState ack_result) {
if (key_queue_.empty()) {
- LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
- << "don't seem to have sent it to the renderer!";
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
} else if (key_queue_.front().type != type) {
- LOG(ERROR) << "We seem to have a different key type sent from "
- << "the renderer. (" << key_queue_.front().type << " vs. "
- << type << "). Ignoring event.";
-
// Something must be wrong. Clear the |key_queue_| and char event
// suppression so that we can resume from the error.
key_queue_.clear();
- client_->OnUnexpectedEventAck(false);
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
} else {
NativeWebKeyboardEvent front_item = key_queue_.front();
key_queue_.pop_front();
- client_->OnKeyboardEventAck(front_item, ack_result);
-
+ ack_handler_->OnKeyboardEventAck(front_item, ack_result);
// WARNING: This ImmediateInputRouter can be deallocated at this point
// (i.e. in the case of Ctrl+W, where the call to
// HandleKeyboardEvent destroys this ImmediateInputRouter).
@@ -530,7 +530,7 @@ void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) {
// Process the unhandled wheel event here before calling
// ForwardWheelEventWithLatencyInfo() since it will mutate
// current_wheel_event_.
- client_->OnWheelEventAck(current_wheel_event_.event, ack_result);
+ ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result);
// Now send the next (coalesced) mouse wheel event.
if (!coalesced_mouse_wheel_events_.empty()) {
@@ -544,7 +544,7 @@ void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) {
void ImmediateInputRouter::ProcessGestureAck(int type,
InputEventAckState ack_result) {
const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- client_->OnGestureEventAck(
+ ack_handler_->OnGestureEventAck(
gesture_event_filter_->GetGestureEventAwaitingAck(), ack_result);
gesture_event_filter_->ProcessGestureAck(processed, type);
}
@@ -556,4 +556,19 @@ void ImmediateInputRouter::ProcessTouchAck(
touch_event_queue_->ProcessTouchAck(ack_result, latency_info);
}
+void ImmediateInputRouter::HandleGestureScroll(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ if (!enable_no_touch_to_renderer_while_scrolling_)
+ return;
+
+ // Once scrolling is started stop forwarding touch move events to renderer.
+ if (gesture_event.event.type == WebInputEvent::GestureScrollBegin)
+ touch_event_queue_->set_no_touch_move_to_renderer(true);
+
+ if (gesture_event.event.type == WebInputEvent::GestureScrollEnd ||
+ gesture_event.event.type == WebInputEvent::GestureFlingStart) {
+ touch_event_queue_->set_no_touch_move_to_renderer(false);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router.h b/chromium/content/browser/renderer_host/input/immediate_input_router.h
index 270ca3dc67e..1d1a0c0e168 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.h
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router.h
@@ -21,6 +21,7 @@ struct LatencyInfo;
namespace content {
class GestureEventFilter;
+class InputAckHandler;
class InputRouterClient;
class RenderProcessHost;
class RenderWidgetHostImpl;
@@ -33,11 +34,13 @@ class CONTENT_EXPORT ImmediateInputRouter
public:
ImmediateInputRouter(RenderProcessHost* process,
InputRouterClient* client,
+ InputAckHandler* ack_handler,
int routing_id);
virtual ~ImmediateInputRouter();
// InputRouter
- virtual bool SendInput(IPC::Message* message) OVERRIDE;
+ virtual void Flush() OVERRIDE;
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE;
virtual void SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
virtual void SendWheelEvent(
@@ -59,7 +62,6 @@ class CONTENT_EXPORT ImmediateInputRouter
virtual bool ShouldForwardTouchEvent() const OVERRIDE;
virtual bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE;
- virtual bool HasQueuedGestureEvents() const OVERRIDE;
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -73,12 +75,14 @@ class CONTENT_EXPORT ImmediateInputRouter
}
private:
+ friend class ImmediateInputRouterTest;
+
// TouchEventQueueClient
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
- bool SendMoveCaret(IPC::Message* message);
- bool SendSelectRange(IPC::Message* message);
+ bool SendMoveCaret(scoped_ptr<IPC::Message> message);
+ bool SendSelectRange(scoped_ptr<IPC::Message> message);
bool Send(IPC::Message* message);
// Transmits the given input event an as an IPC::Message. This is an internal
@@ -127,11 +131,15 @@ private:
void ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency_info);
+ void HandleGestureScroll(
+ const GestureEventWithLatencyInfo& gesture_event);
+
int routing_id() const { return routing_id_; }
RenderProcessHost* process_;
InputRouterClient* client_;
+ InputAckHandler* ack_handler_;
int routing_id_;
// (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK.
@@ -186,6 +194,10 @@ private:
// not sent to the renderer.
bool has_touch_handler_;
+ // Whether enabling the optimization that sending no touch move events to
+ // renderer while scrolling.
+ bool enable_no_touch_to_renderer_while_scrolling_;
+
scoped_ptr<TouchEventQueue> touch_event_queue_;
scoped_ptr<GestureEventFilter> gesture_event_filter_;
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc b/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
index ed725ee1a10..0e4767a3239 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
@@ -8,6 +8,8 @@
#include "content/browser/renderer_host/input/gesture_event_filter.h"
#include "content/browser/renderer_host/input/immediate_input_router.h"
#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/input_router_unittest.h"
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
#include "content/common/input_messages.h"
@@ -15,11 +17,11 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#if defined(OS_WIN) || defined(USE_AURA)
#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
#endif
using base::TimeDelta;
@@ -100,266 +102,22 @@ bool EventListIsSubset(const ScopedVector<ui::TouchEvent>& subset,
} // namespace
-class MockInputRouterClient : public InputRouterClient {
+class ImmediateInputRouterTest : public InputRouterTest {
public:
- MockInputRouterClient()
- : input_router_(NULL),
- in_flight_event_count_(0),
- has_touch_handler_(false),
- ack_count_(0),
- unexpected_event_ack_called_(false),
- ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN),
- filter_state_(INPUT_EVENT_ACK_STATE_NOT_CONSUMED),
- is_shortcut_(false),
- allow_send_key_event_(true),
- send_called_(false),
- send_immediately_called_(false) {
- }
- virtual ~MockInputRouterClient() {
- }
-
- // InputRouterClient
- virtual InputEventAckState FilterInputEvent(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) OVERRIDE {
- return filter_state_;
- }
-
- // Called each time a WebInputEvent IPC is sent.
- virtual void IncrementInFlightEventCount() OVERRIDE {
- ++in_flight_event_count_;
- }
-
- // Called each time a WebInputEvent ACK IPC is received.
- virtual void DecrementInFlightEventCount() OVERRIDE {
- --in_flight_event_count_;
- }
-
- // Called when the renderer notifies that it has touch event handlers.
- virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE {
- has_touch_handler_ = has_handlers;
- }
-
- virtual bool OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) OVERRIDE {
- send_called_ = true;
- sent_key_event_ = key_event;
- *is_shortcut = is_shortcut_;
-
- return allow_send_key_event_;
- }
-
- virtual bool OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE {
- send_called_ = true;
- sent_wheel_event_ = wheel_event;
-
- return true;
- }
-
- virtual bool OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
- send_called_ = true;
- sent_mouse_event_ = mouse_event;
-
- return true;
- }
-
- virtual bool OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
- send_called_ = true;
- sent_touch_event_ = touch_event;
-
- return true;
- }
-
- virtual bool OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
- send_called_ = true;
- sent_gesture_event_ = gesture_event;
-
- return input_router_->ShouldForwardGestureEvent(gesture_event);
- }
-
- virtual bool OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_mouse_event_ = mouse_event;
-
- return true;
- }
-
- virtual bool OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_touch_event_ = touch_event;
-
- return true;
- }
-
- virtual bool OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
- send_immediately_called_ = true;
- immediately_sent_gesture_event_ = gesture_event;
-
- return true;
- }
-
- // Called upon event ack receipt from the renderer.
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_key_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnWheelEventAck(const WebMouseWheelEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_wheel_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- acked_touch_event_ = event;
- RecordAckCalled(ack_result);
- }
- virtual void OnGestureEventAck(const WebGestureEvent& event,
- InputEventAckState ack_result) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- RecordAckCalled(ack_result);
- }
- virtual void OnUnexpectedEventAck(bool bad_message) OVERRIDE {
- VLOG(1) << __FUNCTION__ << " called!";
- unexpected_event_ack_called_ = true;
- }
-
- void ExpectSendCalled(bool called) {
- EXPECT_EQ(called, send_called_);
- send_called_ = false;
- }
- void ExpectSendImmediatelyCalled(bool called) {
- EXPECT_EQ(called, send_immediately_called_);
- send_immediately_called_ = false;
- }
- void ExpectAckCalled(int times) {
- EXPECT_EQ(times, ack_count_);
- ack_count_ = 0;
- }
-
- void set_input_router(InputRouter* input_router) {
- input_router_ = input_router;
- }
- bool has_touch_handler() const { return has_touch_handler_; }
- InputEventAckState ack_state() const { return ack_state_; }
- void set_filter_state(InputEventAckState filter_state) {
- filter_state_ = filter_state;
- }
- bool unexpected_event_ack_called() const {
- return unexpected_event_ack_called_;
- }
- const NativeWebKeyboardEvent& acked_keyboard_event() {
- return acked_key_event_;
- }
- const WebMouseWheelEvent& acked_wheel_event() {
- return acked_wheel_event_;
- }
- const TouchEventWithLatencyInfo& acked_touch_event() {
- return acked_touch_event_;
- }
- void set_is_shortcut(bool is_shortcut) {
- is_shortcut_ = is_shortcut;
- }
- void set_allow_send_key_event(bool allow) {
- allow_send_key_event_ = allow;
- }
- const NativeWebKeyboardEvent& sent_key_event() {
- return sent_key_event_;
- }
- const MouseWheelEventWithLatencyInfo& sent_wheel_event() {
- return sent_wheel_event_;
- }
- const MouseEventWithLatencyInfo& sent_mouse_event() {
- return sent_mouse_event_;
- }
- const GestureEventWithLatencyInfo& sent_gesture_event() {
- return sent_gesture_event_;
- }
- const MouseEventWithLatencyInfo& immediately_sent_mouse_event() {
- return immediately_sent_mouse_event_;
- }
- const TouchEventWithLatencyInfo& immediately_sent_touch_event() {
- return immediately_sent_touch_event_;
- }
- const GestureEventWithLatencyInfo& immediately_sent_gesture_event() {
- return immediately_sent_gesture_event_;
- }
-
- private:
- void RecordAckCalled(InputEventAckState ack_result) {
- ++ack_count_;
- ack_state_ = ack_result;
- }
-
- InputRouter* input_router_;
- int in_flight_event_count_;
- bool has_touch_handler_;
-
- int ack_count_;
- bool unexpected_event_ack_called_;
- InputEventAckState ack_state_;
- InputEventAckState filter_state_;
- NativeWebKeyboardEvent acked_key_event_;
- WebMouseWheelEvent acked_wheel_event_;
- TouchEventWithLatencyInfo acked_touch_event_;
-
- bool is_shortcut_;
- bool allow_send_key_event_;
- bool send_called_;
- NativeWebKeyboardEvent sent_key_event_;
- MouseWheelEventWithLatencyInfo sent_wheel_event_;
- MouseEventWithLatencyInfo sent_mouse_event_;
- TouchEventWithLatencyInfo sent_touch_event_;
- GestureEventWithLatencyInfo sent_gesture_event_;
-
- bool send_immediately_called_;
- MouseEventWithLatencyInfo immediately_sent_mouse_event_;
- TouchEventWithLatencyInfo immediately_sent_touch_event_;
- GestureEventWithLatencyInfo immediately_sent_gesture_event_;
-};
-
-class ImmediateInputRouterTest : public testing::Test {
- public:
- ImmediateInputRouterTest() {
- }
- virtual ~ImmediateInputRouterTest() {
- }
+ ImmediateInputRouterTest() {}
+ virtual ~ImmediateInputRouterTest() {}
protected:
- // testing::Test
- virtual void SetUp() {
- browser_context_.reset(new TestBrowserContext());
- process_.reset(new MockRenderProcessHost(browser_context_.get()));
- client_.reset(new MockInputRouterClient());
- input_router_.reset(new ImmediateInputRouter(
- process_.get(),
- client_.get(),
- MSG_ROUTING_NONE));
- client_->set_input_router(input_router_.get());
- }
- virtual void TearDown() {
- // Process all pending tasks to avoid leaks.
- base::MessageLoop::current()->RunUntilIdle();
-
- input_router_.reset();
- client_.reset();
- process_.reset();
- browser_context_.reset();
+ // InputRouterTest
+ virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
+ InputRouterClient* client,
+ InputAckHandler* handler,
+ int routing_id) OVERRIDE {
+ return scoped_ptr<InputRouter>(
+ new ImmediateInputRouter(process, client, handler, routing_id));
}
- void SendInputEventACK(WebInputEvent::Type type,
+ void SendInputEventACK(WebKit::WebInputEvent::Type type,
InputEventAckState ack_result) {
scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
@@ -367,177 +125,16 @@ class ImmediateInputRouterTest : public testing::Test {
input_router_->OnMessageReceived(*response);
}
- void SimulateKeyboardEvent(WebInputEvent::Type type) {
- NativeWebKeyboardEvent key_event;
- key_event.type = type;
- key_event.windowsKeyCode = ui::VKEY_L; // non-null made up value.
- input_router_->SendKeyboardEvent(key_event, ui::LatencyInfo());
- client_->ExpectSendCalled(true);
- EXPECT_EQ(type, client_->sent_key_event().type);
- EXPECT_EQ(key_event.windowsKeyCode,
- client_->sent_key_event().windowsKeyCode);
- }
-
- void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.deltaX = dX;
- wheel_event.deltaY = dY;
- wheel_event.modifiers = modifiers;
- wheel_event.hasPreciseScrollingDeltas = precise;
- input_router_->SendWheelEvent(
- MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
- EXPECT_EQ(dX, client_->sent_wheel_event().event.deltaX);
- }
-
- void SimulateMouseMove(int x, int y, int modifiers) {
- WebMouseEvent mouse_event;
- mouse_event.type = WebInputEvent::MouseMove;
- mouse_event.x = mouse_event.windowX = x;
- mouse_event.y = mouse_event.windowY = y;
- mouse_event.modifiers = modifiers;
- input_router_->SendMouseEvent(
- MouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- client_->ExpectSendImmediatelyCalled(true);
- EXPECT_EQ(mouse_event.type, client_->sent_mouse_event().event.type);
- EXPECT_EQ(x, client_->sent_mouse_event().event.x);
- EXPECT_EQ(mouse_event.type,
- client_->immediately_sent_mouse_event().event.type);
- EXPECT_EQ(x, client_->immediately_sent_mouse_event().event.x);
- }
-
- void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.phase = phase;
- input_router_->SendWheelEvent(
- MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
- EXPECT_EQ(phase, client_->sent_wheel_event().event.phase);
- }
-
- // Inject provided synthetic WebGestureEvent instance.
- void SimulateGestureEventCore(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice,
- WebGestureEvent* gesture_event) {
- gesture_event->type = type;
- gesture_event->sourceDevice = sourceDevice;
- GestureEventWithLatencyInfo gesture_with_latency(
- *gesture_event, ui::LatencyInfo());
- input_router_->SendGestureEvent(gesture_with_latency);
- client_->ExpectSendCalled(true);
- EXPECT_EQ(type, client_->sent_gesture_event().event.type);
- EXPECT_EQ(sourceDevice, client_->sent_gesture_event().event.sourceDevice);
- }
-
- // Inject simple synthetic WebGestureEvent instances.
- void SimulateGestureEvent(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- SimulateGestureEventCore(type, sourceDevice, &gesture_event);
- }
-
- void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.scrollUpdate.deltaX = dX;
- gesture_event.data.scrollUpdate.deltaY = dY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
- }
-
- void SimulateGesturePinchUpdateEvent(float scale,
- float anchorX,
- float anchorY,
- int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.pinchUpdate.scale = scale;
- gesture_event.x = anchorX;
- gesture_event.y = anchorY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GesturePinchUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
- }
-
- // Inject synthetic GestureFlingStart events.
- void SimulateGestureFlingStartEvent(
- float velocityX,
- float velocityY,
- WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- gesture_event.data.flingStart.velocityX = velocityX;
- gesture_event.data.flingStart.velocityY = velocityY;
- SimulateGestureEventCore(WebInputEvent::GestureFlingStart, sourceDevice,
- &gesture_event);
- }
-
- // Set the timestamp for the touch-event.
- void SetTouchTimestamp(base::TimeDelta timestamp) {
- touch_event_.timeStampSeconds = timestamp.InSecondsF();
- }
-
- // Sends a touch event (irrespective of whether the page has a touch-event
- // handler or not).
- void SendTouchEvent() {
- input_router_->SendTouchEvent(
- TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()));
-
- // Mark all the points as stationary. And remove the points that have been
- // released.
- int point = 0;
- for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
- if (touch_event_.touches[i].state == WebTouchPoint::StateReleased)
- continue;
-
- touch_event_.touches[point] = touch_event_.touches[i];
- touch_event_.touches[point].state =
- WebTouchPoint::StateStationary;
- ++point;
- }
- touch_event_.touchesLength = point;
- touch_event_.type = WebInputEvent::Undefined;
- }
-
- int PressTouchPoint(int x, int y) {
- if (touch_event_.touchesLength == touch_event_.touchesLengthCap)
- return -1;
- WebTouchPoint& point =
- touch_event_.touches[touch_event_.touchesLength];
- point.id = touch_event_.touchesLength;
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- point.state = WebTouchPoint::StatePressed;
- point.radiusX = point.radiusY = 1.f;
- ++touch_event_.touchesLength;
- touch_event_.type = WebInputEvent::TouchStart;
- return point.id;
- }
-
- void MoveTouchPoint(int index, int x, int y) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- WebTouchPoint& point = touch_event_.touches[index];
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- touch_event_.touches[index].state = WebTouchPoint::StateMoved;
- touch_event_.type = WebInputEvent::TouchMove;
- }
-
- void ReleaseTouchPoint(int index) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- touch_event_.touches[index].state = WebTouchPoint::StateReleased;
- touch_event_.type = WebInputEvent::TouchEnd;
+ ImmediateInputRouter* input_router() const {
+ return static_cast<ImmediateInputRouter*>(input_router_.get());
}
void set_debounce_interval_time_ms(int ms) {
- input_router_->gesture_event_filter()->debounce_interval_time_ms_ = ms;
+ input_router()->gesture_event_filter()->debounce_interval_time_ms_ = ms;
}
void set_maximum_tap_gap_time_ms(int delay_ms) {
- input_router_->gesture_event_filter()->maximum_tap_gap_time_ms_ = delay_ms;
+ input_router()->gesture_event_filter()->maximum_tap_gap_time_ms_ = delay_ms;
}
size_t TouchEventQueueSize() {
@@ -548,8 +145,16 @@ class ImmediateInputRouterTest : public testing::Test {
return touch_event_queue()->GetLatestEvent().event;
}
+ void EnableNoTouchToRendererWhileScrolling() {
+ input_router()->enable_no_touch_to_renderer_while_scrolling_ = true;
+ }
+
+ bool no_touch_move_to_renderer() {
+ return touch_event_queue()->no_touch_move_to_renderer_;
+ }
+
TouchEventQueue* touch_event_queue() const {
- return input_router_->touch_event_queue();
+ return input_router()->touch_event_queue();
}
unsigned GestureEventLastQueueEventSize() {
@@ -590,18 +195,8 @@ class ImmediateInputRouterTest : public testing::Test {
}
GestureEventFilter* gesture_event_filter() const {
- return input_router_->gesture_event_filter();
+ return input_router()->gesture_event_filter();
}
-
- scoped_ptr<MockRenderProcessHost> process_;
- scoped_ptr<MockInputRouterClient> client_;
- scoped_ptr<ImmediateInputRouter> input_router_;
-
- private:
- base::MessageLoopForUI message_loop_;
- WebTouchEvent touch_event_;
-
- scoped_ptr<TestBrowserContext> browser_context_;
};
#if GTEST_HAS_PARAM_TEST
@@ -613,8 +208,8 @@ class ImmediateInputRouterWithSourceTest
#endif // GTEST_HAS_PARAM_TEST
TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
- input_router_->SendInput(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4)));
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
EXPECT_EQ(1u, process_->sink().message_count());
ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
process_->sink().GetMessageAt(0),
@@ -623,12 +218,12 @@ TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
process_->sink().ClearMessages();
// Send two more messages without acking.
- input_router_->SendInput(
- new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8)));
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8))));
EXPECT_EQ(0u, process_->sink().message_count());
- input_router_->SendInput(
- new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12)));
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12))));
EXPECT_EQ(0u, process_->sink().message_count());
// Now ack the first message.
@@ -654,17 +249,20 @@ TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
}
TEST_F(ImmediateInputRouterTest, CoalescesCaretMove) {
- input_router_->SendInput(new InputMsg_MoveCaret(0, gfx::Point(1, 2)));
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(1, 2))));
EXPECT_EQ(1u, process_->sink().message_count());
ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(
process_->sink().GetMessageAt(0), gfx::Point(1, 2));
process_->sink().ClearMessages();
// Send two more messages without acking.
- input_router_->SendInput(new InputMsg_MoveCaret(0, gfx::Point(5, 6)));
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(5, 6))));
EXPECT_EQ(0u, process_->sink().message_count());
- input_router_->SendInput(new InputMsg_MoveCaret(0, gfx::Point(9, 10)));
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(9, 10))));
EXPECT_EQ(0u, process_->sink().message_count());
// Now ack the first message.
@@ -697,7 +295,7 @@ TEST_F(ImmediateInputRouterTest, HandledInputEvent) {
EXPECT_EQ(0u, process_->sink().message_count());
// OnKeyboardEventAck should be triggered without actual ack.
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
// As the event was acked already, keyboard event queue should be
// empty.
@@ -705,14 +303,14 @@ TEST_F(ImmediateInputRouterTest, HandledInputEvent) {
}
TEST_F(ImmediateInputRouterTest, ClientCanceledKeyboardEvent) {
- client_->set_allow_send_key_event(false);
+ client_->set_allow_send_event(false);
// Simulate a keyboard event.
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
// Make sure no input event is sent to the renderer.
EXPECT_EQ(0u, process_->sink().message_count());
- client_->ExpectAckCalled(0);
+ ack_handler_->ExpectAckCalled(0);
}
TEST_F(ImmediateInputRouterTest, ShortcutKeyboardEvent) {
@@ -734,7 +332,7 @@ TEST_F(ImmediateInputRouterTest, NoncorrespondingKeyEvents) {
SendInputEventACK(WebInputEvent::KeyUp,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(client_->unexpected_event_ack_called());
+ EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
}
// Tests ported from RenderWidgetHostTest --------------------------------------
@@ -754,8 +352,9 @@ TEST_F(ImmediateInputRouterTest, HandleKeyEventsWeSent) {
// Send the simulated response from the renderer back.
SendInputEventACK(WebInputEvent::RawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- client_->ExpectAckCalled(1);
- EXPECT_EQ(WebInputEvent::RawKeyDown, client_->acked_keyboard_event().type);
+ ack_handler_->ExpectAckCalled(1);
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ ack_handler_->acked_keyboard_event().type);
}
TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) {
@@ -763,7 +362,7 @@ TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) {
SendInputEventACK(WebInputEvent::RawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- client_->ExpectAckCalled(0);
+ ack_handler_->ExpectAckCalled(0);
}
TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
@@ -786,7 +385,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
// so that additional input events can be processed before
// we turn off coalescing.
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -796,7 +395,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -806,7 +405,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, process_->sink().message_count());
// FIXME(kouhei): Below is testing gesture event filter. Maybe separate test?
@@ -909,7 +508,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollBegin,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -919,7 +518,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -929,7 +528,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -939,7 +538,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
SendInputEventACK(WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, process_->sink().message_count());
}
@@ -1192,14 +791,14 @@ TEST_P(ImmediateInputRouterWithSourceTest, GestureFlingCancelsFiltered) {
SendInputEventACK(WebInputEvent::GestureFlingStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(2U, process_->sink().message_count());
SendInputEventACK(WebInputEvent::GestureFlingCancel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, GestureEventLastQueueEventSize());
// GFC before previous GFS is acked.
@@ -1218,7 +817,7 @@ TEST_P(ImmediateInputRouterWithSourceTest, GestureFlingCancelsFiltered) {
SendInputEventACK(WebInputEvent::GestureFlingCancel,
INPUT_EVENT_ACK_STATE_CONSUMED);
base::MessageLoop::current()->RunUntilIdle();
- client_->ExpectAckCalled(2);
+ ack_handler_->ExpectAckCalled(2);
EXPECT_EQ(0U, GestureEventLastQueueEventSize());
// GFS is added to the queue if another event is pending
@@ -1563,18 +1162,18 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueue) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(1U, TouchEventQueueSize());
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, TouchEventQueueSize());
- client_->ExpectAckCalled(1);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
EXPECT_EQ(0U, process_->sink().message_count());
}
@@ -1615,8 +1214,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueFlush) {
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(31U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
@@ -1663,8 +1262,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(2U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchStart,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
process_->sink().ClearMessages();
// Coalesced touch-move events should be sent.
@@ -1678,8 +1277,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(1U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(10);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(10);
process_->sink().ClearMessages();
// ACK the release.
@@ -1688,8 +1287,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchEnd,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
}
// Tests that an event that has already been sent but hasn't been ack'ed yet
@@ -1844,8 +1443,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(2);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(2);
EXPECT_EQ(0U, process_->sink().message_count());
process_->sink().ClearMessages();
@@ -1854,8 +1453,8 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendTouchEvent();
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(WebInputEvent::TouchEnd,
- client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
// Send a press-event, followed by move and release events, and another press
// event, before the ACK for the first press event comes back. All of the
@@ -1883,8 +1482,9 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchEnd, client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(4);
+ EXPECT_EQ(WebInputEvent::TouchEnd,
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(4);
EXPECT_EQ(1U, TouchEventQueueSize());
process_->sink().ClearMessages();
@@ -1892,8 +1492,9 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchStart, client_->acked_touch_event().event.type);
- client_->ExpectAckCalled(1);
+ EXPECT_EQ(WebInputEvent::TouchStart,
+ ack_handler_->acked_touch_event().event.type);
+ ack_handler_->ExpectAckCalled(1);
EXPECT_EQ(0U, TouchEventQueueSize());
// Send a second press event. Even though the first touch had NO_CONSUMER,
@@ -2030,7 +1631,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueConsumerIgnoreMultiFinger) {
EXPECT_EQ(1U, process_->sink().message_count());
EXPECT_EQ(2U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
process_->sink().ClearMessages();
// ACK the press with NO_CONSUMED_EXISTS. This should release the queued
@@ -2040,7 +1641,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueConsumerIgnoreMultiFinger) {
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, TouchEventQueueSize());
EXPECT_EQ(WebInputEvent::TouchMove,
- client_->acked_touch_event().event.type);
+ ack_handler_->acked_touch_event().event.type);
ReleaseTouchPoint(2);
ReleaseTouchPoint(1);
@@ -2118,11 +1719,11 @@ TEST_F(ImmediateInputRouterTest, AckedTouchEventState) {
for (size_t i = 0; i < arraysize(acks); ++i) {
SendInputEventACK(acks[i],
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(acks[i], client_->acked_touch_event().event.type);
+ EXPECT_EQ(acks[i], ack_handler_->acked_touch_event().event.type);
ScopedVector<ui::TouchEvent> acked;
MakeUITouchEventsFromWebTouchEvents(
- client_->acked_touch_event(), &acked, coordinate_system);
+ ack_handler_->acked_touch_event(), &acked, coordinate_system);
bool success = EventListIsSubset(acked, expected_events);
EXPECT_TRUE(success) << "Failed on step: " << i;
if (!success)
@@ -2151,9 +1752,9 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Check that the correct unhandled wheel event was received.
- client_->ExpectAckCalled(1);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, client_->ack_state());
- EXPECT_EQ(client_->acked_wheel_event().deltaY, -5);
+ ack_handler_->ExpectAckCalled(1);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
+ EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
// Check that the second event was sent.
EXPECT_EQ(1U, process_->sink().message_count());
@@ -2162,7 +1763,96 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
process_->sink().ClearMessages();
// Check that the correct unhandled wheel event was received.
- EXPECT_EQ(client_->acked_wheel_event().deltaY, -5);
+ EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
}
+// Tests that no touch move events are sent to renderer during scrolling.
+TEST_F(ImmediateInputRouterTest, NoTouchMoveWhileScroll) {
+ EnableNoTouchToRendererWhileScrolling();
+ set_debounce_interval_time_ms(0);
+ input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+ process_->sink().ClearMessages();
+
+ // First touch press.
+ PressTouchPoint(0, 1);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Touch move will trigger scroll.
+ MoveTouchPoint(0, 20, 5);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, process_->sink().message_count());
+ EXPECT_TRUE(no_touch_move_to_renderer());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Touch move should not be sent to renderer.
+ MoveTouchPoint(0, 30, 5);
+ SendTouchEvent();
+ EXPECT_EQ(0U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+
+ // Touch moves become ScrollUpdate.
+ SimulateGestureScrollUpdateEvent(20, 4, 0);
+ EXPECT_TRUE(no_touch_move_to_renderer());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Touch move should not be sent to renderer.
+ MoveTouchPoint(0, 65, 10);
+ SendTouchEvent();
+ EXPECT_EQ(0U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+
+ // Touch end should still be sent to renderer.
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchEnd,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // On GestureScrollEnd, resume sending touch moves to renderer.
+ SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, process_->sink().message_count());
+ EXPECT_FALSE(no_touch_move_to_renderer());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::GestureScrollEnd,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Now touch events should come through to renderer.
+ PressTouchPoint(80, 10);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ MoveTouchPoint(0, 80, 20);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::TouchEnd,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_ack_handler.h b/chromium/content/browser/renderer_host/input/input_ack_handler.h
new file mode 100644
index 00000000000..3e09b07cd03
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_ack_handler.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "content/port/browser/event_with_latency_info.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+// Provided customized ack response for input events.
+class CONTENT_EXPORT InputAckHandler {
+ public:
+ virtual ~InputAckHandler() {}
+
+ // Called upon event ack receipt from the renderer.
+ virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) = 0;
+ virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ InputEventAckState ack_result) = 0;
+ virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) = 0;
+ virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ InputEventAckState ack_result) = 0;
+
+ enum UnexpectedEventAckType {
+ UNEXPECTED_ACK,
+ UNEXPECTED_EVENT_TYPE,
+ BAD_ACK_MESSAGE
+ };
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue.cc b/chromium/content/browser/renderer_host/input/input_queue.cc
new file mode 100644
index 00000000000..c10500b9c08
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue.cc
@@ -0,0 +1,183 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/input_queue.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/input/browser_input_event.h"
+#include "content/browser/renderer_host/input/input_queue_client.h"
+#include "content/common/input/event_packet.h"
+#include "content/common/input/input_event.h"
+
+namespace content {
+
+// A specialized EventPacket with utility methods for dispatched event handling.
+class InputQueue::BrowserEventPacket : public EventPacket {
+ public:
+ typedef ScopedVector<BrowserInputEvent> BrowserInputEvents;
+
+ BrowserEventPacket() : weak_factory_(this) {}
+ virtual ~BrowserEventPacket() {}
+
+ // Validate the response and signal dispatch to the processed events.
+ // Undelivered events will be re-enqueued, and any generated followup events
+ // will be inserted at the same relative order as their generating event.
+ AckResult ValidateAndDispatchAck(int64 packet_id,
+ const InputEventDispositions& dispositions) {
+ if (!Validate(packet_id, dispositions))
+ return ACK_INVALID;
+
+ // Empty the packet; events will be re-enqueued as necessary.
+ InputEvents dispatched_events;
+ events_.swap(dispatched_events);
+
+ // The packet could be deleted as a result of event dispatch; use a local
+ // weak ref to ensure proper shutdown.
+ base::WeakPtr<EventPacket> weak_ref_this = weak_factory_.GetWeakPtr();
+
+ BrowserInputEvents followup_events;
+ for (size_t i = 0; i < dispatched_events.size(); ++i) {
+ // Take ownership of the event.
+ scoped_ptr<BrowserInputEvent> event(
+ static_cast<BrowserInputEvent*>(dispatched_events[i]));
+ dispatched_events[i] = NULL;
+
+ // Re-enqueue undelivered events.
+ InputEventDisposition disposition = dispositions[i];
+ if (disposition == INPUT_EVENT_COULD_NOT_DELIVER) {
+ Add(event.PassAs<InputEvent>());
+ continue;
+ }
+
+ event->OnDispatched(disposition, &followup_events);
+
+ // TODO(jdduke): http://crbug.com/274029
+ if (!weak_ref_this.get())
+ return ACK_SHUTDOWN;
+
+ AddAll(&followup_events);
+ }
+ return ACK_OK;
+ }
+
+ protected:
+ // Add and take ownership of events in |followup_events|.
+ void AddAll(BrowserInputEvents* followup_events) {
+ for (BrowserInputEvents::iterator iter = followup_events->begin();
+ iter != followup_events->end();
+ ++iter) {
+ Add(scoped_ptr<InputEvent>(*iter));
+ }
+ followup_events->weak_clear();
+ }
+
+ // Perform a sanity check of the ack against the current packet.
+ // |packet_id| should match that of this packet, and |dispositions| should
+ // be of size equal to the number of events in this packet.
+ bool Validate(int64 packet_id,
+ const InputEventDispositions& dispositions) const {
+ if (packet_id != id())
+ return false;
+
+ if (dispositions.size() != size())
+ return false;
+
+ return true;
+ }
+
+ private:
+ base::WeakPtrFactory<EventPacket> weak_factory_;
+};
+
+InputQueue::InputQueue(InputQueueClient* client)
+ : client_(client),
+ next_packet_id_(1),
+ flush_requested_(false),
+ in_flush_packet_(new BrowserEventPacket()),
+ pending_flush_packet_(new BrowserEventPacket()) {
+ DCHECK(client_);
+}
+
+InputQueue::~InputQueue() {}
+
+void InputQueue::QueueEvent(scoped_ptr<BrowserInputEvent> event) {
+ DCHECK(event);
+ DCHECK(event->valid());
+ pending_flush_packet_->Add(event.PassAs<InputEvent>());
+ RequestFlushIfNecessary();
+}
+
+void InputQueue::BeginFlush() {
+ // Ignore repeated flush attempts.
+ if (!flush_requested_)
+ return;
+
+ DCHECK(!FlushInProgress());
+ DCHECK(!pending_flush_packet_->empty());
+
+ flush_requested_ = false;
+ in_flush_packet_.swap(pending_flush_packet_);
+ DeliverInFlushPacket();
+}
+
+InputQueue::AckResult InputQueue::OnEventPacketAck(
+ int64 packet_id,
+ const InputEventDispositions& dispositions) {
+ if (!FlushInProgress())
+ return ACK_UNEXPECTED;
+
+ TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "AckPacket",
+ "id", packet_id);
+
+ AckResult ack_result =
+ in_flush_packet_->ValidateAndDispatchAck(packet_id, dispositions);
+
+ if (ack_result != ACK_OK)
+ return ack_result;
+
+ if (FlushInProgress()) {
+ DeliverInFlushPacket();
+ } else {
+ TRACE_EVENT_ASYNC_END0("input", "InputQueueFlush", this);
+ client_->DidFinishFlush();
+ RequestFlushIfNecessary();
+ }
+
+ return ACK_OK;
+}
+
+size_t InputQueue::QueuedEventCount() const {
+ return in_flush_packet_->size() + pending_flush_packet_->size();
+}
+
+void InputQueue::DeliverInFlushPacket() {
+ DCHECK(FlushInProgress());
+ TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "DeliverPacket",
+ "id", next_packet_id_);
+ in_flush_packet_->set_id(next_packet_id_++);
+ client_->Deliver(*in_flush_packet_);
+}
+
+void InputQueue::RequestFlushIfNecessary() {
+ if (flush_requested_)
+ return;
+
+ // Defer flush requests until the current flush has finished.
+ if (FlushInProgress())
+ return;
+
+ // No additional events to flush.
+ if (pending_flush_packet_->empty())
+ return;
+
+ TRACE_EVENT_ASYNC_BEGIN0("input", "InputQueueFlush", this);
+ TRACE_EVENT_ASYNC_STEP0("input", "InputQueueFlush", this, "Request");
+ flush_requested_ = true;
+ client_->SetNeedsFlush();
+}
+
+bool InputQueue::FlushInProgress() const { return !in_flush_packet_->empty(); }
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_queue.h b/chromium/content/browser/renderer_host/input/input_queue.h
new file mode 100644
index 00000000000..2c7acb707d2
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue.h
@@ -0,0 +1,82 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/common/input/input_event_disposition.h"
+
+namespace content {
+
+class BrowserInputEvent;
+class EventPacketAck;
+class InputQueueClient;
+
+// |InputQueue| handles browser input event batching and response.
+// Event packets are assembled into sequential event packets. A flush entails
+// delivery and dispatch of a single event packet, and continues until the
+// packet is ack'ed and all its events have been dispatched to the renderer.
+class CONTENT_EXPORT InputQueue {
+ public:
+ // The |client| should outlive the InputQueue.
+ InputQueue(InputQueueClient* client);
+ virtual ~InputQueue();
+
+ // If a flush is in progress, |event| will be dispatched in the next flush.
+ // If no flush is in progress, a flush will be requested if necessary.
+ // |event| is assumed to be both non-NULL and valid.
+ void QueueEvent(scoped_ptr<BrowserInputEvent> event);
+
+ // Initiates the flush of the pending event packet to |client_|, if necessary.
+ // This should only be called in response to |client_->SetNeedsFlush()|.
+ void BeginFlush();
+
+ // Called by the owner upon EventPacket responses from the sender target. This
+ // will dispatch event acks for events with a corresponding |ack_handler|.
+ enum AckResult {
+ ACK_OK, // |acked_packet| was processed successfully.
+ ACK_UNEXPECTED, // |acked_packet| was unexpected; no flush was in-progress.
+ ACK_INVALID, // |acked_packet| contains invalid data.
+ ACK_SHUTDOWN // |acked_packet| processing triggered queue shutdown.
+ };
+ AckResult OnEventPacketAck(int64 packet_id,
+ const InputEventDispositions& dispositions);
+
+ // Total number of evenst in the queue, both being flushed and pending flush.
+ size_t QueuedEventCount() const;
+
+ protected:
+ friend class InputQueueTest;
+
+ // Delivers |in_flush_packet_| to the client.
+ void DeliverInFlushPacket();
+
+ // Requests a flush via |client_| if the necessary request has not been made.
+ void RequestFlushIfNecessary();
+
+ // True when |in_flush_packet_| is non-empty.
+ bool FlushInProgress() const;
+
+ private:
+ InputQueueClient* client_;
+
+ // Used to assign unique, non-zero ID's to each delivered EventPacket.
+ int64 next_packet_id_;
+
+ // Avoid spamming the client with redundant flush requests.
+ bool flush_requested_;
+
+ class BrowserEventPacket;
+ scoped_ptr<BrowserEventPacket> in_flush_packet_;
+ scoped_ptr<BrowserEventPacket> pending_flush_packet_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue_client.h b/chromium/content/browser/renderer_host/input/input_queue_client.h
new file mode 100644
index 00000000000..f1151d92fed
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue_client.h
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "content/common/input/input_event_disposition.h"
+
+namespace content {
+
+class EventPacket;
+
+class InputQueueClient {
+ public:
+ virtual ~InputQueueClient() {}
+
+ // Used by the flush process for sending batched events to the desired target.
+ virtual void Deliver(const EventPacket& packet) = 0;
+
+ // Signalled when the InputQueue has received and dispatched
+ // event ACK's from the previous flush.
+ virtual void DidFinishFlush() = 0;
+
+ // Signalled when the InputQueue receives an input event.
+ virtual void SetNeedsFlush() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue_unittest.cc b/chromium/content/browser/renderer_host/input/input_queue_unittest.cc
new file mode 100644
index 00000000000..2d183d96cca
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_queue_unittest.cc
@@ -0,0 +1,363 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/browser_input_event.h"
+#include "content/browser/renderer_host/input/input_queue.h"
+#include "content/browser/renderer_host/input/input_queue_client.h"
+#include "content/common/input/event_packet.h"
+#include "content/common/input/input_event.h"
+#include "content/common/input/ipc_input_event_payload.h"
+#include "content/common/input/web_input_event_payload.h"
+#include "content/common/input_messages.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/latency_info.h"
+
+namespace content {
+namespace {
+
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+
+class InputQueueTest : public testing::Test,
+ public InputQueueClient,
+ public BrowserInputEventClient {
+ public:
+ InputQueueTest()
+ : queue_(new InputQueue(this)),
+ routing_id_(0),
+ num_flush_completions_(0),
+ num_flush_requests_(0),
+ num_packet_deliveries_(0),
+ next_input_id_(1) {}
+
+ // InputQueueClient
+ virtual void Deliver(const EventPacket& packet) OVERRIDE {
+ EXPECT_LT(0u, packet.size());
+ ++num_packet_deliveries_;
+ current_packet_id_ = packet.id();
+ current_packet_dispositions_.resize(packet.size(), INPUT_EVENT_UNHANDLED);
+ }
+
+ virtual void DidFinishFlush() OVERRIDE { ++num_flush_completions_; }
+ virtual void SetNeedsFlush() OVERRIDE { ++num_flush_requests_; }
+
+ // BrowserInputEventClient
+ virtual void OnDispatched(const BrowserInputEvent& event,
+ InputEventDisposition disposition) OVERRIDE {
+ acked_dispositions_.push_back(disposition);
+ }
+
+ virtual void OnDispatched(
+ const BrowserInputEvent& event,
+ InputEventDisposition disposition,
+ ScopedVector<BrowserInputEvent>* followup) OVERRIDE {
+ acked_followup_dispositions_.push_back(disposition);
+ if (event_to_inject_)
+ followup->push_back(event_to_inject_.release());
+ }
+
+ int num_flush_requests() const { return num_flush_requests_; }
+ int num_flush_completions() const { return num_flush_completions_; }
+ int num_packet_deliveries() const { return num_packet_deliveries_; }
+
+ protected:
+ scoped_ptr<BrowserInputEvent> CreateIPCInputEvent(IPC::Message* message) {
+ return BrowserInputEvent::Create(
+ NextInputID(),
+ IPCInputEventPayload::Create(make_scoped_ptr(message)),
+ this);
+ }
+
+ scoped_ptr<BrowserInputEvent> CreateWebInputEvent(
+ WebInputEvent::Type web_type) {
+ WebKit::WebMouseEvent mouse;
+ WebKit::WebMouseWheelEvent wheel;
+ WebKit::WebTouchEvent touch;
+ WebKit::WebGestureEvent gesture;
+ WebKit::WebKeyboardEvent keyboard;
+
+ WebKit::WebInputEvent* web_event = NULL;
+ if (WebInputEvent::isMouseEventType(web_type))
+ web_event = &mouse;
+ else if (WebInputEvent::isKeyboardEventType(web_type))
+ web_event = &keyboard;
+ else if (WebInputEvent::isTouchEventType(web_type))
+ web_event = &touch;
+ else if (WebInputEvent::isGestureEventType(web_type))
+ web_event = &gesture;
+ else
+ web_event = &wheel;
+ web_event->type = web_type;
+
+ return BrowserInputEvent::Create(
+ NextInputID(),
+ WebInputEventPayload::Create(*web_event, ui::LatencyInfo(), false),
+ this);
+ }
+
+ void QueueEvent(IPC::Message* message) {
+ queue_->QueueEvent(CreateIPCInputEvent(message));
+ }
+
+ void QueueEvent(WebInputEvent::Type web_type) {
+ queue_->QueueEvent(CreateWebInputEvent(web_type));
+ }
+
+ bool Flush(InputEventDisposition disposition) {
+ StartFlush();
+ return FinishFlush(disposition);
+ }
+
+ void StartFlush() {
+ acked_dispositions_.clear();
+ acked_followup_dispositions_.clear();
+ current_packet_id_ = 0;
+ current_packet_dispositions_.clear();
+ queue_->BeginFlush();
+ }
+
+ bool FinishFlush(InputEventDisposition disposition) {
+ if (!current_packet_id_)
+ return false;
+ current_packet_dispositions_ = InputEventDispositions(
+ current_packet_dispositions_.size(), disposition);
+ return InputQueue::ACK_OK ==
+ queue_->OnEventPacketAck(current_packet_id_,
+ current_packet_dispositions_);
+ }
+
+ int64 NextInputID() { return next_input_id_++; }
+
+ scoped_ptr<InputQueue> queue_;
+
+ int routing_id_;
+ int64 current_packet_id_;
+ InputEventDispositions current_packet_dispositions_;
+
+ InputEventDispositions acked_dispositions_;
+ InputEventDispositions acked_followup_dispositions_;
+ scoped_ptr<BrowserInputEvent> event_to_inject_;
+
+ int num_flush_completions_;
+ int num_flush_requests_;
+ int num_packet_deliveries_;
+ int next_input_id_;
+};
+
+TEST_F(InputQueueTest, SetNeedsFlushOnQueueEvent) {
+ EXPECT_EQ(0, num_flush_requests());
+
+ QueueEvent(WebInputEvent::MouseDown);
+ EXPECT_EQ(1, num_flush_requests());
+
+ // Additional queued events should not trigger additional flush requests.
+ QueueEvent(WebInputEvent::MouseUp);
+ EXPECT_EQ(1, num_flush_requests());
+ QueueEvent(WebInputEvent::TouchStart);
+ EXPECT_EQ(1, num_flush_requests());
+}
+
+TEST_F(InputQueueTest, NoSetNeedsFlushOnQueueIfFlushing) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(1, num_flush_requests());
+
+ StartFlush();
+ EXPECT_EQ(1, num_flush_requests());
+ EXPECT_EQ(1, num_packet_deliveries());
+
+ // Events queued after a flush will not trigger an additional flush request.
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(1, num_flush_requests());
+ QueueEvent(WebInputEvent::GestureScrollEnd);
+ EXPECT_EQ(1, num_flush_requests());
+}
+
+TEST_F(InputQueueTest, SetNeedsFlushAfterDidFinishFlushIfEventsQueued) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(1, num_flush_requests());
+
+ StartFlush();
+ EXPECT_EQ(1, num_packet_deliveries());
+
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(1, num_flush_requests());
+
+ // An additional flush request is sent for the event queued after the flush.
+ ASSERT_TRUE(current_packet_id_);
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
+ EXPECT_EQ(1, num_flush_completions());
+ EXPECT_EQ(2, num_flush_requests());
+}
+
+TEST_F(InputQueueTest, EventPacketSentAfterFlush) {
+ EXPECT_EQ(0, num_packet_deliveries());
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(0, num_packet_deliveries());
+ StartFlush();
+ EXPECT_EQ(1, num_packet_deliveries());
+}
+
+TEST_F(InputQueueTest, AcksHandledInProperOrder) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::GestureScrollEnd);
+ QueueEvent(WebInputEvent::GestureFlingStart);
+
+ queue_->BeginFlush();
+ ASSERT_EQ(3u, current_packet_dispositions_.size());
+ current_packet_dispositions_[0] = INPUT_EVENT_IMPL_THREAD_CONSUMED;
+ current_packet_dispositions_[1] = INPUT_EVENT_MAIN_THREAD_CONSUMED;
+ current_packet_dispositions_[2] = INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS;
+ queue_->OnEventPacketAck(current_packet_id_, current_packet_dispositions_);
+ EXPECT_EQ(1, num_flush_completions());
+
+ ASSERT_EQ(3u, acked_dispositions_.size());
+ EXPECT_EQ(acked_dispositions_[0], INPUT_EVENT_IMPL_THREAD_CONSUMED);
+ EXPECT_EQ(acked_dispositions_[1], INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(acked_dispositions_[2], INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
+}
+
+TEST_F(InputQueueTest, FollowupWhenFollowupEventNotConsumed) {
+ InputEventDisposition unconsumed_dispositions[] = {
+ INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS,
+ INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED,
+ INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS
+ };
+ for (size_t i = 0; i < arraysize(unconsumed_dispositions); ++i) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::TouchStart);
+ QueueEvent(WebInputEvent::TouchMove);
+
+ Flush(unconsumed_dispositions[i]);
+ EXPECT_EQ(1u, acked_dispositions_.size()) << i;
+ EXPECT_EQ(2u, acked_followup_dispositions_.size()) << i;
+ }
+}
+
+TEST_F(InputQueueTest, NoFollowupWhenFollowupEventConsumed) {
+ InputEventDisposition consumed_dispositions[] = {
+ INPUT_EVENT_IMPL_THREAD_CONSUMED,
+ INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED,
+ INPUT_EVENT_MAIN_THREAD_CONSUMED
+ };
+ for (size_t i = 0; i < arraysize(consumed_dispositions); ++i) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::TouchStart);
+ QueueEvent(WebInputEvent::TouchMove);
+
+ Flush(consumed_dispositions[i]);
+ EXPECT_EQ(3u, acked_dispositions_.size()) << i;
+ EXPECT_EQ(0u, acked_followup_dispositions_.size()) << i;
+ }
+}
+
+TEST_F(InputQueueTest, FlushOnEmptyQueueIgnored) {
+ Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(0, num_flush_requests());
+ EXPECT_EQ(0, num_flush_completions());
+
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(1, num_flush_requests());
+ EXPECT_EQ(1, num_flush_completions());
+
+ Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(1, num_flush_requests());
+ EXPECT_EQ(1, num_flush_completions());
+}
+
+TEST_F(InputQueueTest, FlushContinuesUntilAllEventsProcessed) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::GestureScrollEnd);
+ QueueEvent(WebInputEvent::GestureFlingStart);
+
+ EXPECT_EQ(1, num_flush_requests());
+ Flush(INPUT_EVENT_COULD_NOT_DELIVER);
+ EXPECT_EQ(0, num_flush_completions());
+
+ FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER);
+ EXPECT_EQ(0, num_flush_completions());
+
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
+ EXPECT_EQ(1, num_flush_completions());
+}
+
+TEST_F(InputQueueTest, InvalidPacketAckIgnored) {
+ // Packet never flushed, any ack should be ignored.
+ InputQueue::AckResult result =
+ queue_->OnEventPacketAck(0, InputEventDispositions());
+ EXPECT_EQ(InputQueue::ACK_UNEXPECTED, result);
+
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ StartFlush();
+ // Tamper with the sent packet by adding an extra event.
+ current_packet_dispositions_.push_back(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ bool valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(0, num_flush_completions());
+ EXPECT_FALSE(valid_packet_ack);
+
+ // Fix the packet.
+ current_packet_dispositions_.pop_back();
+ valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(1, num_flush_completions());
+ EXPECT_TRUE(valid_packet_ack);
+
+ // Tamper with the packet by changing the id.
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ StartFlush();
+ int64 packet_ack_id = -1;
+ std::swap(current_packet_id_, packet_ack_id);
+ valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(1, num_flush_completions());
+ EXPECT_FALSE(valid_packet_ack);
+
+ // Fix the packet.
+ std::swap(current_packet_id_, packet_ack_id);
+ valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
+ EXPECT_EQ(2, num_flush_completions());
+ EXPECT_TRUE(valid_packet_ack);
+}
+
+TEST_F(InputQueueTest, InjectedEventsAckedBeforeDidFinishFlush) {
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::TouchMove);
+
+ event_to_inject_ = CreateIPCInputEvent(new InputMsg_Copy(routing_id_));
+ Flush(INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(0, num_flush_completions());
+
+ // The injected event should now be in the event packet.
+ EXPECT_EQ(1u, current_packet_dispositions_.size());
+ EXPECT_EQ(1u, acked_followup_dispositions_.size());
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
+ EXPECT_EQ(1, num_flush_completions());
+
+ QueueEvent(WebInputEvent::GestureScrollBegin);
+ QueueEvent(WebInputEvent::TouchStart);
+ event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
+ Flush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
+ // |event_to_inject_| is now in the event packet.
+ EXPECT_EQ(1u, acked_followup_dispositions_.size());
+ EXPECT_EQ(1u, current_packet_dispositions_.size());
+
+ event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
+ // the next |event_to_inject_| is now in the event packet.
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS));
+
+ EXPECT_EQ(2u, acked_followup_dispositions_.size());
+ EXPECT_EQ(1u, current_packet_dispositions_.size());
+ EXPECT_EQ(1, num_flush_completions());
+
+ ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
+ EXPECT_EQ(2, num_flush_completions());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index 2d8a4c6dd5d..5e4533fc1dd 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -24,10 +24,14 @@ class InputRouter : public IPC::Listener {
public:
virtual ~InputRouter() {}
+ // Should be called only in response to |SetNeedsFlush| requests made via
+ // the |InputRouterClient|.
+ virtual void Flush() = 0;
+
// Send and take ownership of the the given InputMsg_*. This should be used
// only for event types not associated with a WebInputEvent. Returns true on
// success and false otherwise.
- virtual bool SendInput(IPC::Message* message) = 0;
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) = 0;
// WebInputEvents
virtual void SendMouseEvent(
@@ -60,9 +64,6 @@ class InputRouter : public IPC::Listener {
// |gesture_event| to the router.
virtual bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const = 0;
-
- // Returns |true| if the router has any queued or in-flight gesture events.
- virtual bool HasQueuedGestureEvents() const = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_client.h b/chromium/content/browser/renderer_host/input/input_router_client.h
index 9c854224b52..6479332d444 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -61,16 +61,15 @@ class CONTENT_EXPORT InputRouterClient {
virtual bool OnSendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) = 0;
- // Called upon event ack receipt from the renderer.
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) = 0;
- virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
- InputEventAckState ack_result) = 0;
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) = 0;
- virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
- InputEventAckState ack_result) = 0;
- virtual void OnUnexpectedEventAck(bool bad_message) = 0;
+ // Certain router implementations require periodic flushing of queued events.
+ // When this method is called, the client should ensure a timely call, either
+ // synchronous or asynchronous, of |Flush| on the InputRouter.
+ virtual void SetNeedsFlush() = 0;
+
+ // Called when the router has finished flushing all events queued at the time
+ // of the call to Flush. The call will typically be asynchronous with
+ // respect to the call to |Flush| on the InputRouter.
+ virtual void DidFlush() = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_unittest.cc
new file mode 100644
index 00000000000..da1ef1efb70
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_unittest.cc
@@ -0,0 +1,225 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/input_router_unittest.h"
+
+#include "content/browser/renderer_host/input/input_router.h"
+#include "content/common/input_messages.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+#if defined(OS_WIN) || defined(USE_AURA)
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "ui/events/event.h"
+#endif
+
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+using WebKit::WebTouchPoint;
+
+namespace content {
+
+InputRouterTest::InputRouterTest() {}
+InputRouterTest::~InputRouterTest() {}
+
+void InputRouterTest::SetUp() {
+ browser_context_.reset(new TestBrowserContext());
+ process_.reset(new MockRenderProcessHost(browser_context_.get()));
+ client_.reset(new MockInputRouterClient());
+ ack_handler_.reset(new MockInputAckHandler());
+ input_router_ = CreateInputRouter(process_.get(),
+ client_.get(),
+ ack_handler_.get(),
+ MSG_ROUTING_NONE);
+ client_->set_input_router(input_router_.get());
+ ack_handler_->set_input_router(input_router_.get());
+}
+
+void InputRouterTest::TearDown() {
+ // Process all pending tasks to avoid InputRouterTest::leaks.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ input_router_.reset();
+ client_.reset();
+ process_.reset();
+ browser_context_.reset();
+}
+
+void InputRouterTest::SimulateKeyboardEvent(WebInputEvent::Type type) {
+ NativeWebKeyboardEvent key_event;
+ key_event.type = type;
+ key_event.windowsKeyCode = ui::VKEY_L; // non-null made up value.
+ input_router_->SendKeyboardEvent(key_event, ui::LatencyInfo());
+ client_->ExpectSendCalled(true);
+ EXPECT_EQ(type, client_->sent_key_event().type);
+ EXPECT_EQ(key_event.windowsKeyCode,
+ client_->sent_key_event().windowsKeyCode);
+}
+
+void InputRouterTest::SimulateWheelEvent(float dX,
+ float dY,
+ int modifiers,
+ bool precise) {
+ WebMouseWheelEvent wheel_event;
+ wheel_event.type = WebInputEvent::MouseWheel;
+ wheel_event.deltaX = dX;
+ wheel_event.deltaY = dY;
+ wheel_event.modifiers = modifiers;
+ wheel_event.hasPreciseScrollingDeltas = precise;
+ input_router_->SendWheelEvent(
+ MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
+ client_->ExpectSendCalled(true);
+ EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
+ EXPECT_EQ(dX, client_->sent_wheel_event().event.deltaX);
+}
+
+void InputRouterTest::SimulateMouseMove(int x, int y, int modifiers) {
+ WebMouseEvent mouse_event;
+ mouse_event.type = WebInputEvent::MouseMove;
+ mouse_event.x = mouse_event.windowX = x;
+ mouse_event.y = mouse_event.windowY = y;
+ mouse_event.modifiers = modifiers;
+ input_router_->SendMouseEvent(
+ MouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo()));
+ client_->ExpectSendCalled(true);
+ EXPECT_EQ(mouse_event.type, client_->sent_mouse_event().event.type);
+ EXPECT_EQ(x, client_->sent_mouse_event().event.x);
+}
+
+void InputRouterTest::SimulateWheelEventWithPhase(
+ WebMouseWheelEvent::Phase phase) {
+ WebMouseWheelEvent wheel_event;
+ wheel_event.type = WebInputEvent::MouseWheel;
+ wheel_event.phase = phase;
+ input_router_->SendWheelEvent(
+ MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
+ client_->ExpectSendCalled(true);
+ EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
+ EXPECT_EQ(phase, client_->sent_wheel_event().event.phase);
+}
+
+// Inject provided synthetic WebGestureEvent instance.
+void InputRouterTest::SimulateGestureEventCore(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice,
+ WebGestureEvent* gesture_event) {
+ gesture_event->type = type;
+ gesture_event->sourceDevice = sourceDevice;
+ GestureEventWithLatencyInfo gesture_with_latency(
+ *gesture_event, ui::LatencyInfo());
+ input_router_->SendGestureEvent(gesture_with_latency);
+ client_->ExpectSendCalled(true);
+ EXPECT_EQ(type, client_->sent_gesture_event().event.type);
+ EXPECT_EQ(sourceDevice, client_->sent_gesture_event().event.sourceDevice);
+}
+
+// Inject simple synthetic WebGestureEvent instances.
+void InputRouterTest::SimulateGestureEvent(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ WebGestureEvent gesture_event;
+ SimulateGestureEventCore(type, sourceDevice, &gesture_event);
+}
+
+void InputRouterTest::SimulateGestureScrollUpdateEvent(float dX,
+ float dY,
+ int modifiers) {
+ WebGestureEvent gesture_event;
+ gesture_event.data.scrollUpdate.deltaX = dX;
+ gesture_event.data.scrollUpdate.deltaY = dY;
+ gesture_event.modifiers = modifiers;
+ SimulateGestureEventCore(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen, &gesture_event);
+}
+
+void InputRouterTest::SimulateGesturePinchUpdateEvent(float scale,
+ float anchorX,
+ float anchorY,
+ int modifiers) {
+ WebGestureEvent gesture_event;
+ gesture_event.data.pinchUpdate.scale = scale;
+ gesture_event.x = anchorX;
+ gesture_event.y = anchorY;
+ gesture_event.modifiers = modifiers;
+ SimulateGestureEventCore(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchscreen, &gesture_event);
+}
+
+// Inject synthetic GestureFlingStart events.
+void InputRouterTest::SimulateGestureFlingStartEvent(
+ float velocityX,
+ float velocityY,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ WebGestureEvent gesture_event;
+ gesture_event.data.flingStart.velocityX = velocityX;
+ gesture_event.data.flingStart.velocityY = velocityY;
+ SimulateGestureEventCore(WebInputEvent::GestureFlingStart, sourceDevice,
+ &gesture_event);
+}
+
+void InputRouterTest::SimulateTouchEvent(
+ int x,
+ int y) {
+ PressTouchPoint(x, y);
+ SendTouchEvent();
+}
+
+// Set the timestamp for the touch-event.
+void InputRouterTest::SetTouchTimestamp(base::TimeDelta timestamp) {
+ touch_event_.timeStampSeconds = timestamp.InSecondsF();
+}
+
+// Sends a touch event (irrespective of whether the page has a touch-event
+// handler or not).
+void InputRouterTest::SendTouchEvent() {
+ input_router_->SendTouchEvent(
+ TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()));
+
+ // Mark all the points as stationary. And remove the points that have been
+ // released.
+ int point = 0;
+ for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
+ if (touch_event_.touches[i].state == WebTouchPoint::StateReleased)
+ continue;
+
+ touch_event_.touches[point] = touch_event_.touches[i];
+ touch_event_.touches[point].state =
+ WebTouchPoint::StateStationary;
+ ++point;
+ }
+ touch_event_.touchesLength = point;
+ touch_event_.type = WebInputEvent::Undefined;
+}
+
+int InputRouterTest::PressTouchPoint(int x, int y) {
+ if (touch_event_.touchesLength == touch_event_.touchesLengthCap)
+ return -1;
+ WebTouchPoint& point =
+ touch_event_.touches[touch_event_.touchesLength];
+ point.id = touch_event_.touchesLength;
+ point.position.x = point.screenPosition.x = x;
+ point.position.y = point.screenPosition.y = y;
+ point.state = WebTouchPoint::StatePressed;
+ point.radiusX = point.radiusY = 1.f;
+ ++touch_event_.touchesLength;
+ touch_event_.type = WebInputEvent::TouchStart;
+ return point.id;
+}
+
+void InputRouterTest::MoveTouchPoint(int index, int x, int y) {
+ CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
+ WebTouchPoint& point = touch_event_.touches[index];
+ point.position.x = point.screenPosition.x = x;
+ point.position.y = point.screenPosition.y = y;
+ touch_event_.touches[index].state = WebTouchPoint::StateMoved;
+ touch_event_.type = WebInputEvent::TouchMove;
+}
+
+void InputRouterTest::ReleaseTouchPoint(int index) {
+ CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
+ touch_event_.touches[index].state = WebTouchPoint::StateReleased;
+ touch_event_.type = WebInputEvent::TouchEnd;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_unittest.h b/chromium/content/browser/renderer_host/input/input_router_unittest.h
new file mode 100644
index 00000000000..20a68af3fb1
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_unittest.h
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+class InputRouter;
+class MockInputRouterClient;
+
+class InputRouterTest : public testing::Test {
+ public:
+ InputRouterTest();
+ virtual ~InputRouterTest();
+
+ protected:
+ // Called on SetUp.
+ virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
+ InputRouterClient* client,
+ InputAckHandler* handler,
+ int routing_id) = 0;
+
+ // testing::Test
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ void SendInputEventACK(WebKit::WebInputEvent::Type type,
+ InputEventAckState ack_result);
+ void SimulateKeyboardEvent(WebKit::WebInputEvent::Type type);
+ void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise);
+ void SimulateMouseMove(int x, int y, int modifiers);
+ void SimulateWheelEventWithPhase(WebKit::WebMouseWheelEvent::Phase phase);
+ void SimulateGestureEventCore(WebKit::WebInputEvent::Type type,
+ WebKit::WebGestureEvent::SourceDevice sourceDevice,
+ WebKit::WebGestureEvent* gesture_event);
+ void SimulateGestureEvent(WebKit::WebInputEvent::Type type,
+ WebKit::WebGestureEvent::SourceDevice sourceDevice);
+ void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers);
+ void SimulateGesturePinchUpdateEvent(float scale,
+ float anchorX,
+ float anchorY,
+ int modifiers);
+ void SimulateGestureFlingStartEvent(
+ float velocityX,
+ float velocityY,
+ WebKit::WebGestureEvent::SourceDevice sourceDevice);
+ void SimulateTouchEvent(int x, int y);
+ void SetTouchTimestamp(base::TimeDelta timestamp);
+
+ // Sends a touch event (irrespective of whether the page has a touch-event
+ // handler or not).
+ void SendTouchEvent();
+
+ int PressTouchPoint(int x, int y);
+ void MoveTouchPoint(int index, int x, int y);
+ void ReleaseTouchPoint(int index);
+
+ scoped_ptr<MockRenderProcessHost> process_;
+ scoped_ptr<MockInputRouterClient> client_;
+ scoped_ptr<MockInputAckHandler> ack_handler_;
+ scoped_ptr<InputRouter> input_router_;
+
+ private:
+ base::MessageLoopForUI message_loop_;
+ WebKit::WebTouchEvent touch_event_;
+
+ scoped_ptr<TestBrowserContext> browser_context_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_UNITTEST_H_
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
new file mode 100644
index 00000000000..fc97ab3450b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+
+#include "content/browser/renderer_host/input/input_router.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+using WebKit::WebTouchPoint;
+
+namespace content {
+
+MockInputAckHandler::MockInputAckHandler()
+ : input_router_(NULL),
+ ack_count_(0),
+ unexpected_event_ack_called_(false),
+ ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+MockInputAckHandler::~MockInputAckHandler() {}
+
+void MockInputAckHandler::OnKeyboardEventAck(
+ const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_key_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnWheelEventAck(
+ const WebMouseWheelEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_wheel_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnTouchEventAck(
+ const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_touch_event_ = event;
+ RecordAckCalled(ack_result);
+ if (touch_followup_event_)
+ input_router_->SendGestureEvent(*touch_followup_event_);
+}
+
+void MockInputAckHandler::OnGestureEventAck(
+ const WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ acked_gesture_event_ = event;
+ RecordAckCalled(ack_result);
+}
+
+void MockInputAckHandler::OnUnexpectedEventAck(UnexpectedEventAckType type) {
+ VLOG(1) << __FUNCTION__ << " called!";
+ unexpected_event_ack_called_ = true;
+}
+
+void MockInputAckHandler::ExpectAckCalled(int times) {
+ EXPECT_EQ(times, ack_count_);
+ ack_count_ = 0;
+}
+
+void MockInputAckHandler::RecordAckCalled(InputEventAckState ack_result) {
+ ++ack_count_;
+ ack_state_ = ack_result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
new file mode 100644
index 00000000000..604b26b94cb
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/input_ack_handler.h"
+
+namespace content {
+
+class InputRouter;
+
+class MockInputAckHandler : public InputAckHandler {
+ public:
+ MockInputAckHandler();
+ virtual ~MockInputAckHandler();
+
+ // InputAckHandler
+ virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ InputEventAckState ack_result) OVERRIDE;
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
+
+ void ExpectAckCalled(int times);
+
+ void set_input_router(InputRouter* input_router) {
+ input_router_ = input_router;
+ }
+
+ void set_followup_touch_event(scoped_ptr<GestureEventWithLatencyInfo> event) {
+ touch_followup_event_ = event.Pass();
+ }
+
+ bool unexpected_event_ack_called() const {
+ return unexpected_event_ack_called_;
+ }
+ InputEventAckState ack_state() const { return ack_state_; }
+
+ const NativeWebKeyboardEvent& acked_keyboard_event() const {
+ return acked_key_event_;
+ }
+ const WebKit::WebMouseWheelEvent& acked_wheel_event() const {
+ return acked_wheel_event_;
+ }
+ const TouchEventWithLatencyInfo& acked_touch_event() const {
+ return acked_touch_event_;
+ }
+ const WebKit::WebGestureEvent& acked_gesture_event() const {
+ return acked_gesture_event_;
+ }
+
+ private:
+ void RecordAckCalled(InputEventAckState ack_result);
+
+ InputRouter* input_router_;
+
+ int ack_count_;
+ bool unexpected_event_ack_called_;
+ InputEventAckState ack_state_;
+ NativeWebKeyboardEvent acked_key_event_;
+ WebKit::WebMouseWheelEvent acked_wheel_event_;
+ TouchEventWithLatencyInfo acked_touch_event_;
+ WebKit::WebGestureEvent acked_gesture_event_;
+
+ scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
new file mode 100644
index 00000000000..86fb53b6b58
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -0,0 +1,148 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
+
+#include "content/browser/renderer_host/input/input_router.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using WebKit::WebGestureEvent;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebTouchEvent;
+using WebKit::WebTouchPoint;
+
+namespace content {
+
+MockInputRouterClient::MockInputRouterClient()
+ : input_router_(NULL),
+ in_flight_event_count_(0),
+ has_touch_handler_(false),
+ filter_state_(INPUT_EVENT_ACK_STATE_NOT_CONSUMED),
+ is_shortcut_(false),
+ allow_send_event_(true),
+ send_called_(false),
+ send_immediately_called_(false),
+ did_flush_called_(false),
+ set_needs_flush_called_(false) {}
+
+MockInputRouterClient::~MockInputRouterClient() {}
+
+InputEventAckState MockInputRouterClient::FilterInputEvent(
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) {
+ return filter_state_;
+}
+
+void MockInputRouterClient::IncrementInFlightEventCount() {
+ ++in_flight_event_count_;
+}
+
+void MockInputRouterClient::DecrementInFlightEventCount() {
+ --in_flight_event_count_;
+}
+
+void MockInputRouterClient::OnHasTouchEventHandlers(
+ bool has_handlers) {
+ has_touch_handler_ = has_handlers;
+}
+
+bool MockInputRouterClient::OnSendKeyboardEvent(
+ const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ bool* is_shortcut) {
+ send_called_ = true;
+ sent_key_event_ = key_event;
+ *is_shortcut = is_shortcut_;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ send_called_ = true;
+ sent_wheel_event_ = wheel_event;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ send_called_ = true;
+ sent_mouse_event_ = mouse_event;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendTouchEvent(
+ const TouchEventWithLatencyInfo& touch_event) {
+ send_called_ = true;
+ sent_touch_event_ = touch_event;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ send_called_ = true;
+ sent_gesture_event_ = gesture_event;
+
+ return allow_send_event_ &&
+ input_router_->ShouldForwardGestureEvent(gesture_event);
+}
+
+bool MockInputRouterClient::OnSendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ send_immediately_called_ = true;
+ immediately_sent_mouse_event_ = mouse_event;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) {
+ send_immediately_called_ = true;
+ immediately_sent_touch_event_ = touch_event;
+
+ return allow_send_event_;
+}
+
+bool MockInputRouterClient::OnSendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ send_immediately_called_ = true;
+ immediately_sent_gesture_event_ = gesture_event;
+ return allow_send_event_;
+}
+
+void MockInputRouterClient::ExpectSendCalled(bool called) {
+ EXPECT_EQ(called, send_called_);
+ send_called_ = false;
+}
+
+void MockInputRouterClient::ExpectSendImmediatelyCalled(bool called) {
+ EXPECT_EQ(called, send_immediately_called_);
+ send_immediately_called_ = false;
+}
+
+void MockInputRouterClient::ExpectNeedsFlushCalled(bool called) {
+ EXPECT_EQ(called, set_needs_flush_called_);
+ set_needs_flush_called_ = false;
+}
+
+void MockInputRouterClient::ExpectDidFlushCalled(bool called) {
+ EXPECT_EQ(called, did_flush_called_);
+ did_flush_called_ = false;
+}
+
+void MockInputRouterClient::DidFlush() {
+ did_flush_called_ = true;
+}
+
+void MockInputRouterClient::SetNeedsFlush() {
+ set_needs_flush_called_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
new file mode 100644
index 00000000000..a02f73891f0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -0,0 +1,126 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+
+namespace content {
+
+class InputRouter;
+
+class MockInputRouterClient : public InputRouterClient {
+ public:
+ MockInputRouterClient();
+ virtual ~MockInputRouterClient();
+
+ // InputRouterClient
+ virtual InputEventAckState FilterInputEvent(
+ const WebKit::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void IncrementInFlightEventCount() OVERRIDE;
+ virtual void DecrementInFlightEventCount() OVERRIDE;
+ virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
+ virtual bool OnSendKeyboardEvent(
+ const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ bool* is_shortcut) OVERRIDE;
+ virtual bool OnSendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
+ virtual bool OnSendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
+ virtual bool OnSendTouchEvent(
+ const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
+ virtual bool OnSendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual bool OnSendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
+ virtual bool OnSendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
+ virtual bool OnSendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual void DidFlush() OVERRIDE;
+ virtual void SetNeedsFlush() OVERRIDE;
+
+ void ExpectSendCalled(bool called);
+ void ExpectSendImmediatelyCalled(bool called);
+ void ExpectNeedsFlushCalled(bool called);
+ void ExpectDidFlushCalled(bool called);
+
+ void set_input_router(InputRouter* input_router) {
+ input_router_ = input_router;
+ }
+
+ bool has_touch_handler() const { return has_touch_handler_; }
+ void set_filter_state(InputEventAckState filter_state) {
+ filter_state_ = filter_state;
+ }
+ int in_flight_event_count() const {
+ return in_flight_event_count_;
+ }
+ void set_is_shortcut(bool is_shortcut) {
+ is_shortcut_ = is_shortcut;
+ }
+ void set_allow_send_event(bool allow) {
+ allow_send_event_ = allow;
+ }
+ const NativeWebKeyboardEvent& sent_key_event() {
+ return sent_key_event_;
+ }
+ const MouseWheelEventWithLatencyInfo& sent_wheel_event() {
+ return sent_wheel_event_;
+ }
+ const MouseEventWithLatencyInfo& sent_mouse_event() {
+ return sent_mouse_event_;
+ }
+ const GestureEventWithLatencyInfo& sent_gesture_event() {
+ return sent_gesture_event_;
+ }
+ const MouseEventWithLatencyInfo& immediately_sent_mouse_event() {
+ return immediately_sent_mouse_event_;
+ }
+ const TouchEventWithLatencyInfo& immediately_sent_touch_event() {
+ return immediately_sent_touch_event_;
+ }
+ const GestureEventWithLatencyInfo& immediately_sent_gesture_event() {
+ return immediately_sent_gesture_event_;
+ }
+
+ bool did_flush_called() const { return did_flush_called_; }
+ bool needs_flush_called() const { return set_needs_flush_called_; }
+ void set_followup_touch_event(scoped_ptr<GestureEventWithLatencyInfo> event) {
+ touch_followup_event_ = event.Pass();
+ }
+
+ private:
+ InputRouter* input_router_;
+ int in_flight_event_count_;
+ bool has_touch_handler_;
+
+ InputEventAckState filter_state_;
+
+ bool is_shortcut_;
+ bool allow_send_event_;
+ bool send_called_;
+ NativeWebKeyboardEvent sent_key_event_;
+ MouseWheelEventWithLatencyInfo sent_wheel_event_;
+ MouseEventWithLatencyInfo sent_mouse_event_;
+ TouchEventWithLatencyInfo sent_touch_event_;
+ GestureEventWithLatencyInfo sent_gesture_event_;
+
+ bool send_immediately_called_;
+ MouseEventWithLatencyInfo immediately_sent_mouse_event_;
+ TouchEventWithLatencyInfo immediately_sent_touch_event_;
+ GestureEventWithLatencyInfo immediately_sent_gesture_event_;
+
+ bool did_flush_called_;
+ bool set_needs_flush_called_;
+ scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_CLIENT_H_
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.cc b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
index c1675b9952d..e22c05d0f80 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -91,7 +91,8 @@ class CoalescedWebTouchEvent {
TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
: client_(client),
- dispatching_touch_ack_(false) {
+ dispatching_touch_ack_(false),
+ no_touch_move_to_renderer_(false) {
DCHECK(client);
}
@@ -212,6 +213,10 @@ bool TouchEventQueue::ShouldForwardToRenderer(
if (event.type == WebKit::WebInputEvent::TouchStart)
return true;
+ if (event.type == WebKit::WebInputEvent::TouchMove &&
+ no_touch_move_to_renderer_)
+ return false;
+
for (unsigned int i = 0; i < event.touchesLength; ++i) {
const WebKit::WebTouchPoint& point = event.touches[i];
// If a point has been stationary, then don't take it into account.
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.h b/chromium/content/browser/renderer_host/input/touch_event_queue.h
index 23dda66c38b..358fae9c50d 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -61,6 +61,10 @@ class TouchEventQueue {
return touch_queue_.empty();
}
+ void set_no_touch_move_to_renderer(bool value) {
+ no_touch_move_to_renderer_ = value;
+ }
+
private:
friend class MockRenderWidgetHost;
friend class ImmediateInputRouterTest;
@@ -88,6 +92,11 @@ class TouchEventQueue {
// Used to defer touch forwarding when ack dispatch triggers |QueueEvent()|.
bool dispatching_touch_ack_;
+ // Don't send touch move events to renderer. This is enabled when the page
+ // is scrolling. This behaviour is currently enabled only on aura behind a
+ // flag.
+ bool no_touch_move_to_renderer_;
+
DISALLOW_COPY_AND_ASSIGN(TouchEventQueue);
};
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
index eca820bb28b..b5c96c657eb 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -7,8 +7,8 @@
#include "base/logging.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/input/web_input_event_util_posix.h"
-#include "ui/base/keycodes/keyboard_code_conversion_android.h"
-#include "ui/base/keycodes/keyboard_codes_posix.h"
+#include "ui/events/keycodes/keyboard_code_conversion_android.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
new file mode 100644
index 00000000000..c101595c79f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
@@ -0,0 +1,603 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "base/logging.h"
+#include "content/browser/renderer_host/input/web_input_event_util_posix.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/keycodes/keyboard_code_conversion_gtk.h"
+
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebMouseWheelEvent;
+using WebKit::WebKeyboardEvent;
+
+namespace {
+
+// For click count tracking.
+static int num_clicks = 0;
+static GdkWindow* last_click_event_window = 0;
+static gint last_click_time = 0;
+static gint last_click_x = 0;
+static gint last_click_y = 0;
+static WebMouseEvent::Button last_click_button = WebMouseEvent::ButtonNone;
+
+bool ShouldForgetPreviousClick(GdkWindow* window, gint time, gint x, gint y) {
+ static GtkSettings* settings = gtk_settings_get_default();
+
+ if (window != last_click_event_window)
+ return true;
+
+ gint double_click_time = 250;
+ gint double_click_distance = 5;
+ g_object_get(G_OBJECT(settings),
+ "gtk-double-click-time",
+ &double_click_time,
+ "gtk-double-click-distance",
+ &double_click_distance,
+ NULL);
+ return (time - last_click_time) > double_click_time ||
+ std::abs(x - last_click_x) > double_click_distance ||
+ std::abs(y - last_click_y) > double_click_distance;
+}
+
+void ResetClickCountState() {
+ num_clicks = 0;
+ last_click_event_window = 0;
+ last_click_time = 0;
+ last_click_x = 0;
+ last_click_y = 0;
+ last_click_button = WebKit::WebMouseEvent::ButtonNone;
+}
+
+bool IsKeyPadKeyval(guint keyval) {
+ // Keypad keyvals all fall into one range.
+ return keyval >= GDK_KP_Space && keyval <= GDK_KP_9;
+}
+
+double GdkEventTimeToWebEventTime(guint32 time) {
+ // Convert from time in ms to time in sec.
+ return time / 1000.0;
+}
+
+int GdkStateToWebEventModifiers(guint state) {
+ int modifiers = 0;
+ if (state & GDK_SHIFT_MASK)
+ modifiers |= WebInputEvent::ShiftKey;
+ if (state & GDK_CONTROL_MASK)
+ modifiers |= WebInputEvent::ControlKey;
+ if (state & GDK_MOD1_MASK)
+ modifiers |= WebInputEvent::AltKey;
+ if (state & GDK_META_MASK)
+ modifiers |= WebInputEvent::MetaKey;
+ if (state & GDK_BUTTON1_MASK)
+ modifiers |= WebInputEvent::LeftButtonDown;
+ if (state & GDK_BUTTON2_MASK)
+ modifiers |= WebInputEvent::MiddleButtonDown;
+ if (state & GDK_BUTTON3_MASK)
+ modifiers |= WebInputEvent::RightButtonDown;
+ if (state & GDK_LOCK_MASK)
+ modifiers |= WebInputEvent::CapsLockOn;
+ if (state & GDK_MOD2_MASK)
+ modifiers |= WebInputEvent::NumLockOn;
+ return modifiers;
+}
+
+ui::KeyboardCode GdkEventToWindowsKeyCode(const GdkEventKey* event) {
+ static const unsigned int kHardwareCodeToGDKKeyval[] = {
+ 0, // 0x00:
+ 0, // 0x01:
+ 0, // 0x02:
+ 0, // 0x03:
+ 0, // 0x04:
+ 0, // 0x05:
+ 0, // 0x06:
+ 0, // 0x07:
+ 0, // 0x08:
+ 0, // 0x09: GDK_Escape
+ GDK_1, // 0x0A: GDK_1
+ GDK_2, // 0x0B: GDK_2
+ GDK_3, // 0x0C: GDK_3
+ GDK_4, // 0x0D: GDK_4
+ GDK_5, // 0x0E: GDK_5
+ GDK_6, // 0x0F: GDK_6
+ GDK_7, // 0x10: GDK_7
+ GDK_8, // 0x11: GDK_8
+ GDK_9, // 0x12: GDK_9
+ GDK_0, // 0x13: GDK_0
+ GDK_minus, // 0x14: GDK_minus
+ GDK_equal, // 0x15: GDK_equal
+ 0, // 0x16: GDK_BackSpace
+ 0, // 0x17: GDK_Tab
+ GDK_q, // 0x18: GDK_q
+ GDK_w, // 0x19: GDK_w
+ GDK_e, // 0x1A: GDK_e
+ GDK_r, // 0x1B: GDK_r
+ GDK_t, // 0x1C: GDK_t
+ GDK_y, // 0x1D: GDK_y
+ GDK_u, // 0x1E: GDK_u
+ GDK_i, // 0x1F: GDK_i
+ GDK_o, // 0x20: GDK_o
+ GDK_p, // 0x21: GDK_p
+ GDK_bracketleft, // 0x22: GDK_bracketleft
+ GDK_bracketright, // 0x23: GDK_bracketright
+ 0, // 0x24: GDK_Return
+ 0, // 0x25: GDK_Control_L
+ GDK_a, // 0x26: GDK_a
+ GDK_s, // 0x27: GDK_s
+ GDK_d, // 0x28: GDK_d
+ GDK_f, // 0x29: GDK_f
+ GDK_g, // 0x2A: GDK_g
+ GDK_h, // 0x2B: GDK_h
+ GDK_j, // 0x2C: GDK_j
+ GDK_k, // 0x2D: GDK_k
+ GDK_l, // 0x2E: GDK_l
+ GDK_semicolon, // 0x2F: GDK_semicolon
+ GDK_apostrophe, // 0x30: GDK_apostrophe
+ GDK_grave, // 0x31: GDK_grave
+ 0, // 0x32: GDK_Shift_L
+ GDK_backslash, // 0x33: GDK_backslash
+ GDK_z, // 0x34: GDK_z
+ GDK_x, // 0x35: GDK_x
+ GDK_c, // 0x36: GDK_c
+ GDK_v, // 0x37: GDK_v
+ GDK_b, // 0x38: GDK_b
+ GDK_n, // 0x39: GDK_n
+ GDK_m, // 0x3A: GDK_m
+ GDK_comma, // 0x3B: GDK_comma
+ GDK_period, // 0x3C: GDK_period
+ GDK_slash, // 0x3D: GDK_slash
+ 0, // 0x3E: GDK_Shift_R
+ 0, // 0x3F:
+ 0, // 0x40:
+ 0, // 0x41:
+ 0, // 0x42:
+ 0, // 0x43:
+ 0, // 0x44:
+ 0, // 0x45:
+ 0, // 0x46:
+ 0, // 0x47:
+ 0, // 0x48:
+ 0, // 0x49:
+ 0, // 0x4A:
+ 0, // 0x4B:
+ 0, // 0x4C:
+ 0, // 0x4D:
+ 0, // 0x4E:
+ 0, // 0x4F:
+ 0, // 0x50:
+ 0, // 0x51:
+ 0, // 0x52:
+ 0, // 0x53:
+ 0, // 0x54:
+ 0, // 0x55:
+ 0, // 0x56:
+ 0, // 0x57:
+ 0, // 0x58:
+ 0, // 0x59:
+ 0, // 0x5A:
+ 0, // 0x5B:
+ 0, // 0x5C:
+ 0, // 0x5D:
+ 0, // 0x5E:
+ 0, // 0x5F:
+ 0, // 0x60:
+ 0, // 0x61:
+ 0, // 0x62:
+ 0, // 0x63:
+ 0, // 0x64:
+ 0, // 0x65:
+ 0, // 0x66:
+ 0, // 0x67:
+ 0, // 0x68:
+ 0, // 0x69:
+ 0, // 0x6A:
+ 0, // 0x6B:
+ 0, // 0x6C:
+ 0, // 0x6D:
+ 0, // 0x6E:
+ 0, // 0x6F:
+ 0, // 0x70:
+ 0, // 0x71:
+ 0, // 0x72:
+ GDK_Super_L, // 0x73: GDK_Super_L
+ GDK_Super_R, // 0x74: GDK_Super_R
+ };
+
+ // |windows_key_code| has to include a valid virtual-key code even when we
+ // use non-US layouts, e.g. even when we type an 'A' key of a US keyboard
+ // on the Hebrew layout, |windows_key_code| should be VK_A.
+ // On the other hand, |event->keyval| value depends on the current
+ // GdkKeymap object, i.e. when we type an 'A' key of a US keyboard on
+ // the Hebrew layout, |event->keyval| becomes GDK_hebrew_shin and this
+ // ui::WindowsKeyCodeForGdkKeyCode() call returns 0.
+ // To improve compatibilty with Windows, we use |event->hardware_keycode|
+ // for retrieving its Windows key-code for the keys when the
+ // WebCore::windows_key_codeForEvent() call returns 0.
+ // We shouldn't use |event->hardware_keycode| for keys that GdkKeymap
+ // objects cannot change because |event->hardware_keycode| doesn't change
+ // even when we change the layout options, e.g. when we swap a control
+ // key and a caps-lock key, GTK doesn't swap their
+ // |event->hardware_keycode| values but swap their |event->keyval| values.
+ ui::KeyboardCode windows_key_code =
+ ui::WindowsKeyCodeForGdkKeyCode(event->keyval);
+ if (windows_key_code)
+ return windows_key_code;
+
+ if (event->hardware_keycode < arraysize(kHardwareCodeToGDKKeyval)) {
+ int keyval = kHardwareCodeToGDKKeyval[event->hardware_keycode];
+ if (keyval)
+ return ui::WindowsKeyCodeForGdkKeyCode(keyval);
+ }
+
+ // This key is one that keyboard-layout drivers cannot change.
+ // Use |event->keyval| to retrieve its |windows_key_code| value.
+ return ui::WindowsKeyCodeForGdkKeyCode(event->keyval);
+}
+
+// Normalizes event->state to make it Windows/Mac compatible. Since the way
+// of setting modifier mask on X is very different than Windows/Mac as shown
+// in http://crbug.com/127142#c8, the normalization is necessary.
+guint NormalizeEventState(const GdkEventKey* event) {
+ guint mask = 0;
+ switch (GdkEventToWindowsKeyCode(event)) {
+ case ui::VKEY_CONTROL:
+ case ui::VKEY_LCONTROL:
+ case ui::VKEY_RCONTROL:
+ mask = GDK_CONTROL_MASK;
+ break;
+ case ui::VKEY_SHIFT:
+ case ui::VKEY_LSHIFT:
+ case ui::VKEY_RSHIFT:
+ mask = GDK_SHIFT_MASK;
+ break;
+ case ui::VKEY_MENU:
+ case ui::VKEY_LMENU:
+ case ui::VKEY_RMENU:
+ mask = GDK_MOD1_MASK;
+ break;
+ case ui::VKEY_CAPITAL:
+ mask = GDK_LOCK_MASK;
+ break;
+ default:
+ return event->state;
+ }
+ if (event->type == GDK_KEY_PRESS)
+ return event->state | mask;
+ return event->state & ~mask;
+}
+
+// Gets the corresponding control character of a specified key code. See:
+// http://en.wikipedia.org/wiki/Control_characters
+// We emulate Windows behavior here.
+int GetControlCharacter(ui::KeyboardCode windows_key_code, bool shift) {
+ if (windows_key_code >= ui::VKEY_A && windows_key_code <= ui::VKEY_Z) {
+ // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
+ return windows_key_code - ui::VKEY_A + 1;
+ }
+ if (shift) {
+ // following graphics chars require shift key to input.
+ switch (windows_key_code) {
+ // ctrl-@ maps to \x00 (Null byte)
+ case ui::VKEY_2:
+ return 0;
+ // ctrl-^ maps to \x1E (Record separator, Information separator two)
+ case ui::VKEY_6:
+ return 0x1E;
+ // ctrl-_ maps to \x1F (Unit separator, Information separator one)
+ case ui::VKEY_OEM_MINUS:
+ return 0x1F;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ return 0;
+ }
+ } else {
+ switch (windows_key_code) {
+ // ctrl-[ maps to \x1B (Escape)
+ case ui::VKEY_OEM_4:
+ return 0x1B;
+ // ctrl-\ maps to \x1C (File separator, Information separator four)
+ case ui::VKEY_OEM_5:
+ return 0x1C;
+ // ctrl-] maps to \x1D (Group separator, Information separator three)
+ case ui::VKEY_OEM_6:
+ return 0x1D;
+ // ctrl-Enter maps to \x0A (Line feed)
+ case ui::VKEY_RETURN:
+ return 0x0A;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ return 0;
+ }
+ }
+}
+
+} // namespace
+
+namespace content {
+
+// WebKeyboardEvent -----------------------------------------------------------
+
+WebKeyboardEvent WebKeyboardEventBuilder::Build(const GdkEventKey* event) {
+ WebKeyboardEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(NormalizeEventState(event));
+
+ switch (event->type) {
+ case GDK_KEY_RELEASE:
+ result.type = WebInputEvent::KeyUp;
+ break;
+ case GDK_KEY_PRESS:
+ result.type = WebInputEvent::RawKeyDown;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // According to MSDN:
+ // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
+ // Key events with Alt modifier and F10 are system key events.
+ // We just emulate this behavior. It's necessary to prevent webkit from
+ // processing keypress event generated by alt-d, etc.
+ // F10 is not special on Linux, so don't treat it as system key.
+ if (result.modifiers & WebInputEvent::AltKey)
+ result.isSystemKey = true;
+
+ // The key code tells us which physical key was pressed (for example, the
+ // A key went down or up). It does not determine whether A should be lower
+ // or upper case. This is what text does, which should be the keyval.
+ ui::KeyboardCode windows_key_code = GdkEventToWindowsKeyCode(event);
+ result.windowsKeyCode = GetWindowsKeyCodeWithoutLocation(windows_key_code);
+ result.modifiers |= GetLocationModifiersFromWindowsKeyCode(windows_key_code);
+ result.nativeKeyCode = event->hardware_keycode;
+
+ if (result.windowsKeyCode == ui::VKEY_RETURN) {
+ // We need to treat the enter key as a key press of character \r. This
+ // is apparently just how webkit handles it and what it expects.
+ result.unmodifiedText[0] = '\r';
+ } else {
+ // FIXME: fix for non BMP chars
+ result.unmodifiedText[0] =
+ static_cast<int>(gdk_keyval_to_unicode(event->keyval));
+ }
+
+ // If ctrl key is pressed down, then control character shall be input.
+ if (result.modifiers & WebInputEvent::ControlKey) {
+ result.text[0] =
+ GetControlCharacter(ui::KeyboardCode(result.windowsKeyCode),
+ result.modifiers & WebInputEvent::ShiftKey);
+ } else {
+ result.text[0] = result.unmodifiedText[0];
+ }
+
+ result.setKeyIdentifierFromWindowsKeyCode();
+
+ // FIXME: Do we need to set IsAutoRepeat?
+ if (IsKeyPadKeyval(event->keyval))
+ result.modifiers |= WebInputEvent::IsKeyPad;
+
+ return result;
+}
+
+WebKeyboardEvent WebKeyboardEventBuilder::Build(wchar_t character,
+ int state,
+ double timeStampSeconds) {
+ // keyboardEvent(const GdkEventKey*) depends on the GdkEventKey object and
+ // it is hard to use/ it from signal handlers which don't use GdkEventKey
+ // objects (e.g. GtkIMContext signal handlers.) For such handlers, this
+ // function creates a WebInputEvent::Char event without using a
+ // GdkEventKey object.
+ WebKeyboardEvent result;
+ result.type = WebKit::WebInputEvent::Char;
+ result.timeStampSeconds = timeStampSeconds;
+ result.modifiers = GdkStateToWebEventModifiers(state);
+ result.windowsKeyCode = character;
+ result.nativeKeyCode = character;
+ result.text[0] = character;
+ result.unmodifiedText[0] = character;
+
+ // According to MSDN:
+ // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
+ // Key events with Alt modifier and F10 are system key events.
+ // We just emulate this behavior. It's necessary to prevent webkit from
+ // processing keypress event generated by alt-d, etc.
+ // F10 is not special on Linux, so don't treat it as system key.
+ if (result.modifiers & WebInputEvent::AltKey)
+ result.isSystemKey = true;
+
+ return result;
+}
+
+// WebMouseEvent --------------------------------------------------------------
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventButton* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+ result.clickCount = 0;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ result.type = WebInputEvent::MouseDown;
+ break;
+ case GDK_BUTTON_RELEASE:
+ result.type = WebInputEvent::MouseUp;
+ break;
+ case GDK_3BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->button == 1)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->button == 2)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->button == 3)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (result.type == WebInputEvent::MouseDown) {
+ bool forgetPreviousClick = ShouldForgetPreviousClick(
+ event->window, event->time, event->x, event->y);
+
+ if (!forgetPreviousClick && result.button == last_click_button) {
+ ++num_clicks;
+ } else {
+ num_clicks = 1;
+
+ last_click_event_window = event->window;
+ last_click_x = event->x;
+ last_click_y = event->y;
+ last_click_button = result.button;
+ }
+ last_click_time = event->time;
+ }
+ result.clickCount = num_clicks;
+
+ return result;
+}
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventMotion* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ result.type = WebInputEvent::MouseMove;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->state & GDK_BUTTON1_MASK)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->state & GDK_BUTTON2_MASK)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->state & GDK_BUTTON3_MASK)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (ShouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+ ResetClickCountState();
+
+ return result;
+}
+
+WebMouseEvent WebMouseEventBuilder::Build(const GdkEventCrossing* event) {
+ WebMouseEvent result;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ switch (event->type) {
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ // Note that if we sent MouseEnter or MouseLeave to WebKit, it
+ // wouldn't work - they don't result in the proper JavaScript events.
+ // MouseMove does the right thing.
+ result.type = WebInputEvent::MouseMove;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ result.button = WebMouseEvent::ButtonNone;
+ if (event->state & GDK_BUTTON1_MASK)
+ result.button = WebMouseEvent::ButtonLeft;
+ else if (event->state & GDK_BUTTON2_MASK)
+ result.button = WebMouseEvent::ButtonMiddle;
+ else if (event->state & GDK_BUTTON3_MASK)
+ result.button = WebMouseEvent::ButtonRight;
+
+ if (ShouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+ ResetClickCountState();
+
+ return result;
+}
+
+// WebMouseWheelEvent ---------------------------------------------------------
+
+float WebMouseWheelEventBuilder::ScrollbarPixelsPerTick() {
+ // How much should we scroll per mouse wheel event?
+ // - Windows uses 3 lines by default and obeys a system setting.
+ // - Mozilla has a pref that lets you either use the "system" number of lines
+ // to scroll, or lets the user override it.
+ // For the "system" number of lines, it appears they've hardcoded 3.
+ // See case NS_MOUSE_SCROLL in content/events/src/nsEventStateManager.cpp
+ // and InitMouseScrollEvent in widget/src/gtk2/nsCommonWidget.cpp .
+ // - Gtk makes the scroll amount a function of the size of the scroll bar,
+ // which is not available to us here.
+ // Instead, we pick a number that empirically matches Firefox's behavior.
+ return 160.0f / 3.0f;
+}
+
+WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
+ const GdkEventScroll* event) {
+ WebMouseWheelEvent result;
+
+ result.type = WebInputEvent::MouseWheel;
+ result.button = WebMouseEvent::ButtonNone;
+
+ result.timeStampSeconds = GdkEventTimeToWebEventTime(event->time);
+ result.modifiers = GdkStateToWebEventModifiers(event->state);
+ result.x = static_cast<int>(event->x);
+ result.y = static_cast<int>(event->y);
+ result.windowX = result.x;
+ result.windowY = result.y;
+ result.globalX = static_cast<int>(event->x_root);
+ result.globalY = static_cast<int>(event->y_root);
+
+ static const float scrollbarPixelsPerTick = ScrollbarPixelsPerTick();
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+ result.deltaY = scrollbarPixelsPerTick;
+ result.wheelTicksY = 1;
+ break;
+ case GDK_SCROLL_DOWN:
+ result.deltaY = -scrollbarPixelsPerTick;
+ result.wheelTicksY = -1;
+ break;
+ case GDK_SCROLL_LEFT:
+ result.deltaX = scrollbarPixelsPerTick;
+ result.wheelTicksX = 1;
+ break;
+ case GDK_SCROLL_RIGHT:
+ result.deltaX = -scrollbarPixelsPerTick;
+ result.wheelTicksX = -1;
+ break;
+ }
+
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h
new file mode 100644
index 00000000000..6fe16429b35
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GdkEventMotion GdkEventMotion;
+typedef struct _GdkEventCrossing GdkEventCrossing;
+typedef struct _GdkEventScroll GdkEventScroll;
+typedef struct _GdkEventKey GdkEventKey;
+
+namespace content {
+
+class CONTENT_EXPORT WebKeyboardEventBuilder {
+ public:
+ static WebKit::WebKeyboardEvent Build(const GdkEventKey* event);
+ static WebKit::WebKeyboardEvent Build(wchar_t character,
+ int state,
+ double time_secs);
+};
+
+class CONTENT_EXPORT WebMouseEventBuilder {
+ public:
+ static WebKit::WebMouseEvent Build(const GdkEventButton* event);
+ static WebKit::WebMouseEvent Build(const GdkEventMotion* event);
+ static WebKit::WebMouseEvent Build(const GdkEventCrossing* event);
+};
+
+class CONTENT_EXPORT WebMouseWheelEventBuilder {
+ public:
+ static float ScrollbarPixelsPerTick();
+ static WebKit::WebMouseWheelEvent Build(
+ const GdkEventScroll* event);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_GTK_H
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
new file mode 100644
index 00000000000..9498c9eb1be
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
@@ -0,0 +1,171 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/keycodes/keyboard_code_conversion_gtk.h"
+
+using WebKit::WebInputEvent;
+using WebKit::WebKeyboardEvent;
+using WebKit::WebMouseEvent;
+using content::WebMouseEventBuilder;
+using content::WebKeyboardEventBuilder;
+
+namespace {
+
+TEST(WebMouseEventBuilderTest, DoubleClick) {
+ GdkEventButton first_click;
+ first_click.type = GDK_BUTTON_PRESS;
+ first_click.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
+ first_click.x = first_click.y = first_click.x_root = first_click.y_root = 100;
+ first_click.state = 0;
+ first_click.time = 0;
+ first_click.button = 1;
+
+ // Single click works.
+ WebMouseEvent first_click_events =
+ WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Make sure double click works.
+ GdkEventButton second_click = first_click;
+ second_click.time = first_click.time + 100;
+ WebMouseEvent second_click_events =
+ WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(2, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks with a long gap in between aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1000;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks far apart (horizontally) aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.x = first_click.x + 100;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks far apart (vertically) aren't counted as a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.x = first_click.y + 100;
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+
+ // Reset the click count.
+ first_click.time += 10000;
+ first_click_events = WebMouseEventBuilder::Build(&first_click);
+ EXPECT_EQ(1, first_click_events.clickCount);
+
+ // Two clicks on different windows aren't a double click.
+ second_click = first_click;
+ second_click.time = first_click.time + 1;
+ second_click.window = static_cast<GdkWindow*>(GINT_TO_POINTER(2));
+ second_click_events = WebMouseEventBuilder::Build(&second_click);
+ EXPECT_EQ(1, second_click_events.clickCount);
+}
+
+TEST(WebMouseEventBuilderTest, MouseUpClickCount) {
+ GdkEventButton mouse_down;
+ memset(&mouse_down, 0, sizeof(mouse_down));
+ mouse_down.type = GDK_BUTTON_PRESS;
+ mouse_down.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
+ mouse_down.x = mouse_down.y = mouse_down.x_root = mouse_down.y_root = 100;
+ mouse_down.time = 0;
+ mouse_down.button = 1;
+
+ // Properly set the last click time, so that the internal state won't be
+ // affected by previous tests.
+ WebMouseEventBuilder::Build(&mouse_down);
+
+ mouse_down.time += 10000;
+ GdkEventButton mouse_up = mouse_down;
+ mouse_up.type = GDK_BUTTON_RELEASE;
+ WebMouseEvent mouse_down_event;
+ WebMouseEvent mouse_up_event;
+
+ // Click for three times.
+ for (int i = 1; i < 4; ++i) {
+ mouse_down.time += 100;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(i, mouse_down_event.clickCount);
+
+ mouse_up.time = mouse_down.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(i, mouse_up_event.clickCount);
+ }
+
+ // Reset the click count.
+ mouse_down.time += 10000;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(1, mouse_down_event.clickCount);
+
+ // Moving the cursor for a significant distance will reset the click count to
+ // 0.
+ GdkEventMotion mouse_move;
+ memset(&mouse_move, 0, sizeof(mouse_move));
+ mouse_move.type = GDK_MOTION_NOTIFY;
+ mouse_move.window = mouse_down.window;
+ mouse_move.time = mouse_down.time;
+ mouse_move.x = mouse_move.y = mouse_move.x_root = mouse_move.y_root =
+ mouse_down.x + 100;
+ WebMouseEventBuilder::Build(&mouse_move);
+
+ mouse_up.time = mouse_down.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(0, mouse_up_event.clickCount);
+
+ // Reset the click count.
+ mouse_down.time += 10000;
+ mouse_down_event = WebMouseEventBuilder::Build(&mouse_down);
+ EXPECT_EQ(1, mouse_down_event.clickCount);
+
+ // Moving the cursor with a significant delay will reset the click count to 0.
+ mouse_move.time = mouse_down.time + 1000;
+ mouse_move.x = mouse_move.y = mouse_move.x_root = mouse_move.y_root =
+ mouse_down.x;
+ WebMouseEventBuilder::Build(&mouse_move);
+
+ mouse_up.time = mouse_move.time + 50;
+ mouse_up_event = WebMouseEventBuilder::Build(&mouse_up);
+ EXPECT_EQ(0, mouse_up_event.clickCount);
+}
+
+TEST(WebKeyboardEventBuilderTest, NumPadConversion) {
+ // Construct a GDK input event for the numpad "5" key.
+ char five[] = "5";
+ GdkEventKey gdk_event;
+ memset(&gdk_event, 0, sizeof(GdkEventKey));
+ gdk_event.type = GDK_KEY_PRESS;
+ gdk_event.keyval = GDK_KP_5;
+ gdk_event.string = five;
+
+ // Numpad flag should be set on the WebKeyboardEvent.
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(&gdk_event);
+ EXPECT_TRUE(web_event.modifiers & WebInputEvent::IsKeyPad);
+}
+
+} // anonymous namespace
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.h b/chromium/content/browser/renderer_host/input/web_input_event_util.h
index 75870ebc7cc..1abaf8cf34e 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
#include "content/common/content_export.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace WebKit {
class WebKeyboardEvent;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
index 34e4ee96165..e7dc1549cb9 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_POSIX_H_
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index b4959567a31..50bb3ec8310 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -34,7 +34,8 @@ AudioInputDeviceManager::AudioInputDeviceManager(
StreamDeviceInfo fake_device(MEDIA_DEVICE_AUDIO_CAPTURE,
media::AudioManagerBase::kDefaultDeviceName,
media::AudioManagerBase::kDefaultDeviceId,
- 44100, media::CHANNEL_LAYOUT_STEREO, false);
+ 44100, media::CHANNEL_LAYOUT_STEREO,
+ 0, false);
fake_device.session_id = kFakeOpenSessionId;
devices_.push_back(fake_device);
}
@@ -169,19 +170,37 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
DCHECK(IsOnDeviceThread());
StreamDeviceInfo out(info.device.type, info.device.name, info.device.id,
- 0, 0, false);
+ 0, 0, 0, false);
out.session_id = session_id;
+
+ MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
+
if (use_fake_device_) {
// Don't need to query the hardware information if using fake device.
- out.device.sample_rate = 44100;
- out.device.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ input_params.sample_rate = 44100;
+ input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO;
} else {
// Get the preferred sample rate and channel configuration for the
// audio device.
media::AudioParameters params =
audio_manager_->GetInputStreamParameters(info.device.id);
- out.device.sample_rate = params.sample_rate();
- out.device.channel_layout = params.channel_layout();
+ input_params.sample_rate = params.sample_rate();
+ input_params.channel_layout = params.channel_layout();
+ input_params.frames_per_buffer = params.frames_per_buffer();
+
+ // Add preferred output device information if a matching output device
+ // exists.
+ out.device.matched_output_device_id =
+ audio_manager_->GetAssociatedOutputDeviceID(info.device.id);
+ if (!out.device.matched_output_device_id.empty()) {
+ params = audio_manager_->GetOutputStreamParameters(
+ out.device.matched_output_device_id);
+ MediaStreamDevice::AudioDeviceParameters& matched_output_params =
+ out.device.matched_output;
+ matched_output_params.sample_rate = params.sample_rate();
+ matched_output_params.channel_layout = params.channel_layout();
+ matched_output_params.frames_per_buffer = params.frames_per_buffer();
+ }
}
// Return the |session_id| through the listener by posting a task on
@@ -206,6 +225,7 @@ void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(session_id, info.session_id);
DCHECK(GetDevice(session_id) == devices_.end());
+
devices_.push_back(info);
if (listener_)
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index 03b31d2845e..25d8a1722e9 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -177,7 +177,8 @@ TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
int sample_rate(0);
int channel_config(0);
StreamDeviceInfo dummy_device(
- stream_type, device_name, device_id, sample_rate, channel_config, false);
+ stream_type, device_name, device_id, sample_rate, channel_config, 2048,
+ false);
int session_id = manager_->Open(dummy_device);
EXPECT_CALL(*audio_input_listener_,
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 4a2f731a81c..1c021095676 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -51,11 +51,12 @@ AudioInputRendererHost::AudioEntry::~AudioEntry() {}
AudioInputRendererHost::AudioInputRendererHost(
media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager)
+ AudioMirroringManager* audio_mirroring_manager,
+ media::UserInputMonitor* user_input_monitor)
: audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager),
- audio_mirroring_manager_(audio_mirroring_manager) {
-}
+ audio_mirroring_manager_(audio_mirroring_manager),
+ user_input_monitor_(user_input_monitor) {}
AudioInputRendererHost::~AudioInputRendererHost() {
DCHECK(audio_entries_.empty());
@@ -272,20 +273,23 @@ void AudioInputRendererHost::OnCreateStream(
entry->controller = media::AudioInputController::CreateForStream(
audio_manager_->GetMessageLoop(),
this,
- WebContentsAudioInputStream::Create(
- device_id, audio_params, audio_manager_->GetWorkerLoop(),
- audio_mirroring_manager_),
- entry->writer.get());
+ WebContentsAudioInputStream::Create(device_id,
+ audio_params,
+ audio_manager_->GetWorkerLoop(),
+ audio_mirroring_manager_),
+ entry->writer.get(),
+ user_input_monitor_);
} else {
// TODO(henrika): replace CreateLowLatency() with Create() as soon
// as satish has ensured that Speech Input also uses the default low-
// latency path. See crbug.com/112472 for details.
- entry->controller = media::AudioInputController::CreateLowLatency(
- audio_manager_,
- this,
- audio_params,
- device_id,
- entry->writer.get());
+ entry->controller =
+ media::AudioInputController::CreateLowLatency(audio_manager_,
+ this,
+ audio_params,
+ device_id,
+ entry->writer.get(),
+ user_input_monitor_);
}
if (!entry->controller.get()) {
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
index d16ebfad86a..5df1fc6f2f0 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -44,6 +44,7 @@
namespace media {
class AudioManager;
class AudioParameters;
+class UserInputMonitor;
}
namespace content {
@@ -55,10 +56,11 @@ class CONTENT_EXPORT AudioInputRendererHost
public media::AudioInputController::EventHandler {
public:
// Called from UI thread from the owner of this object.
- AudioInputRendererHost(
- media::AudioManager* audio_manager,
- MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager);
+ // |user_input_monitor| is used for typing detection and can be NULL.
+ AudioInputRendererHost(media::AudioManager* audio_manager,
+ MediaStreamManager* media_stream_manager,
+ AudioMirroringManager* audio_mirroring_manager,
+ media::UserInputMonitor* user_input_monitor);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -154,6 +156,9 @@ class CONTENT_EXPORT AudioInputRendererHost
// A map of stream IDs to audio sources.
AudioEntryMap audio_entries_;
+ // Raw pointer of the UserInputMonitor.
+ media::UserInputMonitor* user_input_monitor_;
+
DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
};
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 572abf3e1c6..369e0a87f20 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -29,14 +29,17 @@ void AudioInputSyncWriter::UpdateRecordedBytes(uint32 bytes) {
socket_->Send(&bytes, sizeof(bytes));
}
-uint32 AudioInputSyncWriter::Write(
- const void* data, uint32 size, double volume) {
+uint32 AudioInputSyncWriter::Write(const void* data,
+ uint32 size,
+ double volume,
+ bool key_pressed) {
uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
ptr += current_segment_id_ * shared_memory_segment_size_;
media::AudioInputBuffer* buffer =
reinterpret_cast<media::AudioInputBuffer*>(ptr);
buffer->params.volume = volume;
buffer->params.size = size;
+ buffer->params.key_pressed = key_pressed;
memcpy(buffer->audio, data, size);
if (++current_segment_id_ >= shared_memory_segment_count_)
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
index 4cfe9e3f396..d16911f20c3 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
@@ -28,7 +28,10 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
// media::AudioOutputController::SyncWriter implementation.
virtual void UpdateRecordedBytes(uint32 bytes) OVERRIDE;
- virtual uint32 Write(const void* data, uint32 size, double volume) OVERRIDE;
+ virtual uint32 Write(const void* data,
+ uint32 size,
+ double volume,
+ bool key_pressed) OVERRIDE;
virtual void Close() OVERRIDE;
bool Init();
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
index 53f2eb2ae90..c09dc6ce08b 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -36,6 +36,7 @@ class AudioRendererHost::AudioEntry
int stream_id,
int render_view_id,
const media::AudioParameters& params,
+ const std::string& output_device_id,
const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader);
@@ -88,6 +89,7 @@ class AudioRendererHost::AudioEntry
AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost* host, int stream_id, int render_view_id,
const media::AudioParameters& params,
+ const std::string& output_device_id,
const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader)
@@ -95,7 +97,8 @@ AudioRendererHost::AudioEntry::AudioEntry(
stream_id_(stream_id),
render_view_id_(render_view_id),
controller_(media::AudioOutputController::Create(
- host->audio_manager_, this, params, input_device_id, reader.get())),
+ host->audio_manager_, this, params, output_device_id,
+ input_device_id, reader.get())),
shared_memory_(shared_memory.Pass()),
reader_(reader.Pass()) {
DCHECK(controller_.get());
@@ -301,10 +304,16 @@ void AudioRendererHost::OnCreateStream(
// When the |input_channels| is valid, clients are trying to create a unified
// IO stream which opens an input device mapping to the |session_id|.
- std::string input_device_id;
+ // Initialize the |output_device_id| to an empty string which indicates that
+ // the default device should be used. If a StreamDeviceInfo instance was found
+ // though, then we use the matched output device.
+ std::string input_device_id, output_device_id;
+ const StreamDeviceInfo* info = media_stream_manager_->
+ audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
+ if (info)
+ output_device_id = info->device.matched_output_device_id;
+
if (input_channels > 0) {
- const StreamDeviceInfo* info = media_stream_manager_->
- audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
if (!info) {
SendErrorMessage(stream_id);
DLOG(WARNING) << "No permission has been granted to input stream with "
@@ -346,16 +355,18 @@ void AudioRendererHost::OnCreateStream(
media_observer->OnCreatingAudioStream(render_process_id_, render_view_id);
scoped_ptr<AudioEntry> entry(new AudioEntry(
- this, stream_id, render_view_id, params, input_device_id,
- shared_memory.Pass(),
+ this, stream_id, render_view_id, params, output_device_id,
+ input_device_id, shared_memory.Pass(),
reader.PassAs<media::AudioOutputController::SyncReader>()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
render_process_id_, entry->render_view_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
- if (media_internals_)
- media_internals_->OnSetAudioStreamStatus(this, stream_id, "created");
+ if (media_internals_) {
+ media_internals_->OnAudioStreamCreated(
+ this, stream_id, params, input_device_id);
+ }
}
void AudioRendererHost::OnPlayStream(int stream_id) {
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 42fecc07a96..26c0963e5e8 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -207,8 +207,6 @@ class AudioRendererHostTest : public testing::Test {
}
void Create(bool unified_stream) {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamStatus(_, kStreamId, "created"));
EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _))
.WillOnce(DoAll(Assign(&is_stream_active_, true),
QuitMessageLoop(message_loop_.get())));
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
index 5a03e465533..16e69bf8ad0 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
@@ -23,7 +23,19 @@
namespace content {
namespace {
+
const int kBytesPerPixel = 4;
+
+webrtc::DesktopRect ComputeLetterboxRect(
+ const webrtc::DesktopSize& max_size,
+ const webrtc::DesktopSize& source_size) {
+ gfx::Rect result = media::ComputeLetterboxRegion(
+ gfx::Rect(0, 0, max_size.width(), max_size.height()),
+ gfx::Size(source_size.width(), source_size.height()));
+ return webrtc::DesktopRect::MakeLTRB(
+ result.x(), result.y(), result.right(), result.bottom());
+}
+
} // namespace
class DesktopCaptureDevice::Core
@@ -34,8 +46,7 @@ class DesktopCaptureDevice::Core
scoped_ptr<webrtc::DesktopCapturer> capturer);
// Implementation of VideoCaptureDevice methods.
- void Allocate(int width, int height,
- int frame_rate,
+ void Allocate(const media::VideoCaptureCapability& capture_format,
EventHandler* event_handler);
void Start();
void Stop();
@@ -51,11 +62,16 @@ class DesktopCaptureDevice::Core
// Helper methods that run on the |task_runner_|. Posted from the
// corresponding public methods.
- void DoAllocate(int width, int height, int frame_rate);
+ void DoAllocate(const media::VideoCaptureCapability& capture_format);
void DoStart();
void DoStop();
void DoDeAllocate();
+ // Chooses new output properties based on the supplied source size and the
+ // properties requested to Allocate(), and dispatches OnFrameInfo[Changed]
+ // notifications.
+ void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size);
+
// Helper to schedule capture tasks.
void ScheduleCaptureTimer();
@@ -78,24 +94,23 @@ class DesktopCaptureDevice::Core
base::Lock event_handler_lock_;
EventHandler* event_handler_;
- // Requested size specified to Allocate().
- webrtc::DesktopSize requested_size_;
-
- // Frame rate specified to Allocate().
- int frame_rate_;
+ // Requested video capture format (width, height, frame rate, etc).
+ media::VideoCaptureCapability requested_format_;
- // Empty until the first frame has been captured, and the output dimensions
- // chosen based on the capture frame's size, and any caller-supplied
- // size constraints.
- webrtc::DesktopSize output_size_;
+ // Actual video capture format being generated.
+ media::VideoCaptureCapability capture_format_;
- // Size of the most recently received frame.
+ // Size of frame most recently captured from the source.
webrtc::DesktopSize previous_frame_size_;
- // DesktopFrame into which captured frames are scaled, if the source size does
- // not match |output_size_|. If the source and output have the same dimensions
- // then this is NULL.
- scoped_ptr<webrtc::DesktopFrame> scaled_frame_;
+ // DesktopFrame into which captured frames are down-scaled and/or letterboxed,
+ // depending upon the caller's requested capture capabilities. If frames can
+ // be returned to the caller directly then this is NULL.
+ scoped_ptr<webrtc::DesktopFrame> output_frame_;
+
+ // Sub-rectangle of |output_frame_| into which the source will be scaled
+ // and/or letterboxed.
+ webrtc::DesktopRect output_rect_;
// True between DoStart() and DoStop(). Can't just check |event_handler_|
// because |event_handler_| is used on the caller thread.
@@ -125,12 +140,12 @@ DesktopCaptureDevice::Core::Core(
DesktopCaptureDevice::Core::~Core() {
}
-void DesktopCaptureDevice::Core::Allocate(int width, int height,
- int frame_rate,
- EventHandler* event_handler) {
- DCHECK_GT(width, 0);
- DCHECK_GT(height, 0);
- DCHECK_GT(frame_rate, 0);
+void DesktopCaptureDevice::Core::Allocate(
+ const media::VideoCaptureCapability& capture_format,
+ EventHandler* event_handler) {
+ DCHECK_GT(capture_format.width, 0);
+ DCHECK_GT(capture_format.height, 0);
+ DCHECK_GT(capture_format.frame_rate, 0);
{
base::AutoLock auto_lock(event_handler_lock_);
@@ -139,7 +154,7 @@ void DesktopCaptureDevice::Core::Allocate(int width, int height,
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&Core::DoAllocate, this, width, height, frame_rate));
+ base::Bind(&Core::DoAllocate, this, capture_format));
}
void DesktopCaptureDevice::Core::Start() {
@@ -180,95 +195,76 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
- // If an |output_size_| hasn't yet been chosen then choose one, based upon
- // the source frame size and the requested size supplied to Allocate().
- if (output_size_.is_empty()) {
- // Treat the requested size as upper bounds on width & height.
- // TODO(wez): Constraints should be passed from getUserMedia to Allocate.
- output_size_.set(
- std::min(frame->size().width(), requested_size_.width()),
- std::min(frame->size().height(), requested_size_.height()));
-
- // Inform the EventHandler of the output dimensions, format and frame rate.
- media::VideoCaptureCapability caps;
- caps.width = output_size_.width();
- caps.height = output_size_.height();
- caps.frame_rate = frame_rate_;
- caps.color = media::VideoCaptureCapability::kARGB;
- caps.expected_capture_delay =
- base::Time::kMillisecondsPerSecond / frame_rate_;
- caps.interlaced = false;
-
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_)
- event_handler_->OnFrameInfo(caps);
- }
+ // Handle initial frame size and size changes.
+ RefreshCaptureFormat(frame->size());
if (!started_)
return;
- size_t output_bytes = output_size_.width() * output_size_.height() *
+ webrtc::DesktopSize output_size(capture_format_.width,
+ capture_format_.height);
+ size_t output_bytes = output_size.width() * output_size.height() *
webrtc::DesktopFrame::kBytesPerPixel;
+ const uint8_t* output_data = NULL;
- if (frame->size().equals(output_size_)) {
+ if (frame->size().equals(output_size)) {
// If the captured frame matches the output size, we can return the pixel
// data directly, without scaling.
- scaled_frame_.reset();
-
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_) {
- event_handler_->OnIncomingCapturedFrame(
- frame->data(), output_bytes, base::Time::Now(), 0, false, false);
+ output_data = frame->data();
+ } else {
+ // Otherwise we need to down-scale and/or letterbox to the target format.
+
+ // Allocate a buffer of the correct size to scale the frame into.
+ // |output_frame_| is cleared whenever |output_rect_| changes, so we don't
+ // need to worry about clearing out stale pixel data in letterboxed areas.
+ if (!output_frame_) {
+ output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
+ memset(output_frame_->data(), 0, output_bytes);
}
- return;
- }
-
- // If the output size differs from the frame size (e.g. the source has changed
- // from its original dimensions, or the caller specified size constraints)
- // then we need to scale the image.
- if (!scaled_frame_)
- scaled_frame_.reset(new webrtc::BasicDesktopFrame(output_size_));
- DCHECK(scaled_frame_->size().equals(output_size_));
-
- // If the source frame size changed then clear |scaled_frame_|'s pixels.
- if (!previous_frame_size_.equals(frame->size())) {
- previous_frame_size_ = frame->size();
- memset(scaled_frame_->data(), 0, output_bytes);
+ DCHECK(output_frame_->size().equals(output_size));
+
+ // TODO(wez): Optimize this to scale only changed portions of the output,
+ // using ARGBScaleClip().
+ uint8_t* output_rect_data = output_frame_->data() +
+ output_frame_->stride() * output_rect_.top() +
+ webrtc::DesktopFrame::kBytesPerPixel * output_rect_.left();
+ libyuv::ARGBScale(frame->data(), frame->stride(),
+ frame->size().width(), frame->size().height(),
+ output_rect_data, output_frame_->stride(),
+ output_rect_.width(), output_rect_.height(),
+ libyuv::kFilterBilinear);
+ output_data = output_frame_->data();
}
- // Determine the output size preserving aspect, and center in output buffer.
- gfx::Rect scaled_rect = media::ComputeLetterboxRegion(
- gfx::Rect(0, 0, output_size_.width(), output_size_.height()),
- gfx::Size(frame->size().width(), frame->size().height()));
- uint8* scaled_data = scaled_frame_->data() +
- scaled_frame_->stride() * scaled_rect.y() +
- webrtc::DesktopFrame::kBytesPerPixel * scaled_rect.x();
-
- // TODO(wez): Optimize this to scale only changed portions of the output,
- // using ARGBScaleClip().
- libyuv::ARGBScale(frame->data(), frame->stride(),
- frame->size().width(), frame->size().height(),
- scaled_data, scaled_frame_->stride(),
- scaled_rect.width(), scaled_rect.height(),
- libyuv::kFilterBilinear);
-
base::AutoLock auto_lock(event_handler_lock_);
if (event_handler_) {
- event_handler_->OnIncomingCapturedFrame(
- scaled_frame_->data(), output_bytes,
- base::Time::Now(), 0, false, false);
+ event_handler_->OnIncomingCapturedFrame(output_data, output_bytes,
+ base::Time::Now(), 0, false, false);
}
}
-void DesktopCaptureDevice::Core::DoAllocate(int width,
- int height,
- int frame_rate) {
+void DesktopCaptureDevice::Core::DoAllocate(
+ const media::VideoCaptureCapability& capture_format) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(desktop_capturer_);
- requested_size_.set(width, height);
- output_size_.set(0, 0);
- frame_rate_ = frame_rate;
+ requested_format_ = capture_format;
+
+ // Store requested frame rate and calculate expected delay.
+ capture_format_.frame_rate = requested_format_.frame_rate;
+ capture_format_.expected_capture_delay =
+ base::Time::kMillisecondsPerSecond / requested_format_.frame_rate;
+
+ // Support dynamic changes in resolution only if requester also does.
+ if (requested_format_.frame_size_type ==
+ media::VariableResolutionVideoCaptureDevice) {
+ capture_format_.frame_size_type =
+ media::VariableResolutionVideoCaptureDevice;
+ }
+
+ // This capturer always outputs ARGB, non-interlaced.
+ capture_format_.color = media::PIXEL_FORMAT_ARGB;
+ capture_format_.interlaced = false;
desktop_capturer_->Start(this);
@@ -288,14 +284,63 @@ void DesktopCaptureDevice::Core::DoStart() {
void DesktopCaptureDevice::Core::DoStop() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
started_ = false;
- scaled_frame_.reset();
+ output_frame_.reset();
+ previous_frame_size_.set(0, 0);
}
void DesktopCaptureDevice::Core::DoDeAllocate() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DoStop();
desktop_capturer_.reset();
- output_size_.set(0, 0);
+}
+
+void DesktopCaptureDevice::Core::RefreshCaptureFormat(
+ const webrtc::DesktopSize& frame_size) {
+ if (previous_frame_size_.equals(frame_size))
+ return;
+
+ // Clear the output frame, if any, since it will either need resizing, or
+ // clearing of stale data in letterbox areas, anyway.
+ output_frame_.reset();
+
+ if (previous_frame_size_.is_empty() ||
+ requested_format_.frame_size_type ==
+ media::VariableResolutionVideoCaptureDevice) {
+ // If this is the first frame, or the receiver supports variable resolution
+ // then determine the output size by treating the requested width & height
+ // as maxima.
+ if (frame_size.width() > requested_format_.width ||
+ frame_size.height() > requested_format_.height) {
+ output_rect_ = ComputeLetterboxRect(
+ webrtc::DesktopSize(requested_format_.width,
+ requested_format_.height),
+ frame_size);
+ output_rect_.Translate(-output_rect_.left(), -output_rect_.top());
+ } else {
+ output_rect_ = webrtc::DesktopRect::MakeSize(frame_size);
+ }
+ capture_format_.width = output_rect_.width();
+ capture_format_.height = output_rect_.height();
+
+ {
+ base::AutoLock auto_lock(event_handler_lock_);
+ if (event_handler_) {
+ if (previous_frame_size_.is_empty()) {
+ event_handler_->OnFrameInfo(capture_format_);
+ } else {
+ event_handler_->OnFrameInfoChanged(capture_format_);
+ }
+ }
+ }
+ } else {
+ // Otherwise the output frame size cannot change, so just scale and
+ // letterbox.
+ output_rect_ = ComputeLetterboxRect(
+ webrtc::DesktopSize(capture_format_.width, capture_format_.height),
+ frame_size);
+ }
+
+ previous_frame_size_ = frame_size;
}
void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
@@ -303,7 +348,7 @@ void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
capture_task_posted_ = true;
task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
- base::TimeDelta::FromSeconds(1) / frame_rate_);
+ base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
@@ -343,11 +388,10 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
case DesktopMediaID::TYPE_SCREEN: {
scoped_ptr<webrtc::DesktopCapturer> capturer;
-#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+#if defined(OS_CHROMEOS) && defined(USE_X11)
// ScreenCapturerX11 polls by default, due to poor driver support for
// DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly,
- // so use it. However ARM driver seems to not support this properly, so
- // disable it for ARM. See http://crbug.com/230105 .
+ // so use it.
capturer.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
#elif defined(OS_WIN)
// ScreenCapturerWin disables Aero by default. We don't want it disabled
@@ -394,11 +438,8 @@ DesktopCaptureDevice::~DesktopCaptureDevice() {
void DesktopCaptureDevice::Allocate(
const media::VideoCaptureCapability& capture_format,
- EventHandler* observer) {
- core_->Allocate(capture_format.width,
- capture_format.height,
- capture_format.frame_rate,
- observer);
+ EventHandler* event_handler) {
+ core_->Allocate(capture_format, event_handler);
}
void DesktopCaptureDevice::Start() {
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device.h b/chromium/content/browser/renderer_host/media/desktop_capture_device.h
index 84422d3c5c9..8f60c7de1b8 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device.h
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device.h
@@ -25,7 +25,7 @@ struct DesktopMediaID;
// DesktopCaptureDevice implements VideoCaptureDevice for screens and windows.
// It's essentially an adapter between webrtc::DesktopCapturer and
// VideoCaptureDevice.
-class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
+class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice1 {
public:
// Creates capturer for the specified |source| and then creates
// DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
index 0f14585ea90..2b6479e3cb2 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
@@ -17,7 +17,9 @@
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
using ::testing::_;
+using ::testing::AnyNumber;
using ::testing::DoAll;
+using ::testing::Expectation;
using ::testing::InvokeWithoutArgs;
using ::testing::SaveArg;
@@ -25,6 +27,10 @@ namespace content {
namespace {
+MATCHER_P2(EqualsCaptureCapability, width, height, "") {
+ return arg.width == width && arg.height == height;
+}
+
const int kTestFrameWidth1 = 100;
const int kTestFrameHeight1 = 100;
const int kTestFrameWidth2 = 200;
@@ -38,6 +44,8 @@ class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
MOCK_METHOD0(ReserveOutputBuffer, scoped_refptr<media::VideoFrame>());
MOCK_METHOD0(OnError, void());
MOCK_METHOD1(OnFrameInfo, void(const media::VideoCaptureCapability& info));
+ MOCK_METHOD1(OnFrameInfoChanged,
+ void(const media::VideoCaptureCapability& info));
MOCK_METHOD6(OnIncomingCapturedFrame, void(const uint8* data,
int length,
base::Time timestamp,
@@ -124,7 +132,7 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureCapability capture_format(
- 640, 480, kFrameRate, media::VideoCaptureCapability::kI420, 0, false,
+ 640, 480, kFrameRate, media::PIXEL_FORMAT_I420, 0, false,
media::ConstantResolutionVideoCaptureDevice);
capture_device.Allocate(capture_format, &frame_observer);
capture_device.Start();
@@ -135,14 +143,15 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
EXPECT_GT(caps.width, 0);
EXPECT_GT(caps.height, 0);
EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
EXPECT_FALSE(caps.interlaced);
EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}
-// Test that screen capturer can handle resolution change without crashing.
-TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
+// Test that screen capturer behaves correctly if the source frame size changes
+// but the caller cannot cope with variable resolution output.
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
DesktopCaptureDevice capture_device(
@@ -154,11 +163,14 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
int frame_size;
MockFrameObserver frame_observer;
- EXPECT_CALL(frame_observer, OnFrameInfo(_))
+ Expectation frame_info_called = EXPECT_CALL(frame_observer, OnFrameInfo(_))
.WillOnce(SaveArg<0>(&caps));
+ EXPECT_CALL(frame_observer, OnFrameInfoChanged(_))
+ .Times(0);
EXPECT_CALL(frame_observer, OnError())
.Times(0);
EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
+ .After(frame_info_called)
.WillRepeatedly(DoAll(
SaveArg<1>(&frame_size),
InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
@@ -167,27 +179,93 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
kTestFrameWidth1,
kTestFrameHeight1,
kFrameRate,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
+
capture_device.Allocate(capture_format, &frame_observer);
capture_device.Start();
- // Capture first frame.
+
+ // Capture at least two frames, to ensure that the source frame size has
+ // changed while capturing.
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
done_event.Reset();
- // Capture second frame.
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+
capture_device.Stop();
capture_device.DeAllocate();
EXPECT_EQ(kTestFrameWidth1, caps.width);
EXPECT_EQ(kTestFrameHeight1, caps.height);
EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kARGB, caps.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
EXPECT_FALSE(caps.interlaced);
EXPECT_EQ(caps.width * caps.height * 4, frame_size);
}
+// Test that screen capturer behaves correctly if the source frame size changes
+// and the caller can cope with variable resolution output.
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
+ FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
+
+ DesktopCaptureDevice capture_device(
+ worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+ scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+
+ media::VideoCaptureCapability caps;
+ base::WaitableEvent done_event(false, false);
+
+ MockFrameObserver frame_observer;
+ Expectation frame_info_called = EXPECT_CALL(frame_observer, OnFrameInfo(_))
+ .WillOnce(SaveArg<0>(&caps));
+ Expectation first_info_changed = EXPECT_CALL(frame_observer,
+ OnFrameInfoChanged(EqualsCaptureCapability(kTestFrameWidth2,
+ kTestFrameHeight2)))
+ .After(frame_info_called);
+ Expectation second_info_changed = EXPECT_CALL(frame_observer,
+ OnFrameInfoChanged(EqualsCaptureCapability(kTestFrameWidth1,
+ kTestFrameHeight1)))
+ .After(first_info_changed);
+ EXPECT_CALL(frame_observer, OnFrameInfoChanged(_))
+ .Times(AnyNumber())
+ .After(second_info_changed);
+ EXPECT_CALL(frame_observer, OnError())
+ .Times(0);
+ EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
+ .After(frame_info_called)
+ .WillRepeatedly(
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal));
+
+ media::VideoCaptureCapability capture_format(
+ kTestFrameWidth2,
+ kTestFrameHeight2,
+ kFrameRate,
+ media::PIXEL_FORMAT_I420,
+ 0,
+ false,
+ media::VariableResolutionVideoCaptureDevice);
+
+ capture_device.Allocate(capture_format, &frame_observer);
+ capture_device.Start();
+
+ // Capture at least three frames, to ensure that the source frame size has
+ // changed at least twice while capturing.
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+ done_event.Reset();
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+ done_event.Reset();
+ EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
+
+ capture_device.Stop();
+ capture_device.DeAllocate();
+
+ EXPECT_EQ(kTestFrameWidth1, caps.width);
+ EXPECT_EQ(kTestFrameHeight1, caps.height);
+ EXPECT_EQ(kFrameRate, caps.frame_rate);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
+ EXPECT_FALSE(caps.interlaced);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
index 770e800d402..96a5de2e194 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include "content/browser/renderer_host/media/device_request_message_filter.h"
#include "base/strings/string_number_conversions.h"
@@ -193,7 +192,13 @@ bool DeviceRequestMessageFilter::DoesRawIdMatchGuid(
bool result = hmac.Init(security_origin.spec());
DCHECK(result);
std::vector<uint8> converted_guid;
- base::HexStringToBytes(device_guid, &converted_guid);
+ // |device_guid| is not guaranteed to be a hex string, so check for success.
+ bool success = base::HexStringToBytes(device_guid, &converted_guid);
+
+ if (!success)
+ return false;
+
+ DCHECK_GT(converted_guid.size(), 0u);
return hmac.Verify(
raw_device_id,
base::StringPiece(reinterpret_cast<const char*>(&converted_guid[0]),
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.h b/chromium/content/browser/renderer_host/media/device_request_message_filter.h
index 048e2157871..b684954384c 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.h
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
#include <map>
#include <string>
@@ -75,4 +75,4 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter,
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_CENTER_HOST_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
index 04a7bb69eea..0daad820084 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
@@ -301,4 +301,20 @@ TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicAllowCamera) {
EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
}
+TEST_F(DeviceRequestMessageFilterTest, TestRawIdMatchGuid_EmptyGuid) {
+ GURL origin("https://test.com");
+ const std::string device_guid = "";
+ const std::string raw_device_id = "device";
+ EXPECT_FALSE(DeviceRequestMessageFilter::DoesRawIdMatchGuid(
+ origin, device_guid, raw_device_id));
+}
+
+TEST_F(DeviceRequestMessageFilterTest, TestRawIdMatchGuid_NonHexGuid) {
+ GURL origin("https://test.com");
+ const std::string device_guid = "garbage";
+ const std::string raw_device_id = "device";
+ EXPECT_FALSE(DeviceRequestMessageFilter::DoesRawIdMatchGuid(
+ origin, device_guid, raw_device_id));
+}
+
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 05804266035..2b7d6836326 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -274,16 +274,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateThreeStreams) {
EXPECT_EQ(host_->NumberOfStreams(), 0u);
}
-TEST_F(MediaStreamDispatcherHostTest, FailOpenVideoDevice) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
-
- media::FakeVideoCaptureDevice::SetFailNextCreate();
- SetupFakeUI(false);
- EXPECT_CALL(*host_.get(),
- OnStreamGenerationFailed(kRenderId, kPageRequestId));
- GenerateStreamAndWaitForResult(kPageRequestId, options);
-}
-
TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index 449331198bd..4c234b66ab1 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -740,8 +740,8 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
audio_input_device_manager_->GetOpenedDeviceInfoById(
device_it->session_id);
DCHECK_EQ(info->device.id, device_it->device.id);
- device_it->device.sample_rate = info->device.sample_rate;
- device_it->device.channel_layout = info->device.channel_layout;
+ device_it->device.input = info->device.input;
+ device_it->device.matched_output = info->device.matched_output;
}
audio_devices.push_back(*device_it);
} else if (IsVideoMediaType(device_it->device.type)) {
@@ -949,8 +949,8 @@ void MediaStreamManager::HandleAccessRequestResponse(
if (sample_rate <= 0 || sample_rate > 96000)
sample_rate = 44100;
- device_info.device.sample_rate = sample_rate;
- device_info.device.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ device_info.device.input.sample_rate = sample_rate;
+ device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
}
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 91413710020..a67237a1ed9 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -50,6 +50,7 @@ class MockAudioManager : public AudioManagerPlatform {
virtual void GetAudioInputDeviceNames(
media::AudioDeviceNames* device_names) OVERRIDE {
+ DCHECK(device_names->empty());
if (HasAudioInputDevices()) {
AudioManagerBase::GetAudioInputDeviceNames(device_names);
} else {
diff --git a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
index 8ecbabcd47d..53f5a769313 100644
--- a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/media/midi_dispatcher_host.h"
#include "base/bind.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/browser_context.h"
@@ -57,6 +58,8 @@ void MIDIDispatcherHost::OnRequestSysExPermission(int render_view_id,
void MIDIDispatcherHost::WasSysExPermissionGranted(int render_view_id,
int client_id,
bool success) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantSendMIDISysExMessage(
+ render_process_id_);
Send(new MIDIMsg_SysExPermissionApproved(render_view_id, client_id, success));
}
diff --git a/chromium/content/browser/renderer_host/media/midi_host.cc b/chromium/content/browser/renderer_host/media/midi_host.cc
index 6ed473afeff..0467404bda3 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_host.cc
@@ -9,10 +9,12 @@
#include "base/debug/trace_event.h"
#include "base/process/process.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_observer.h"
+#include "content/public/browser/user_metrics.h"
#include "media/midi/midi_manager.h"
using media::MIDIManager;
@@ -32,8 +34,9 @@ static const uint8 kSysExMessage = 0xf0;
namespace content {
-MIDIHost::MIDIHost(media::MIDIManager* midi_manager)
- : midi_manager_(midi_manager),
+MIDIHost::MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager)
+ : renderer_process_id_(renderer_process_id),
+ midi_manager_(midi_manager),
sent_bytes_in_flight_(0),
bytes_sent_since_last_acknowledgement_(0) {
}
@@ -88,12 +91,15 @@ void MIDIHost::OnStartSession(int client_id) {
output_ports));
}
-void MIDIHost::OnSendData(int port,
+void MIDIHost::OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
if (!midi_manager_)
return;
+ if (data.empty())
+ return;
+
base::AutoLock auto_lock(in_flight_lock_);
// Sanity check that we won't send too much.
@@ -102,47 +108,48 @@ void MIDIHost::OnSendData(int port,
data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
return;
- // For now disallow all System Exclusive messages even if we
- // have permission.
- // TODO(toyoshim): allow System Exclusive if browser has granted
- // this client access. We'll likely need to pass a GURL
- // here to compare against our permissions.
- if (data.size() > 0 && data[0] >= kSysExMessage)
+ if (data[0] >= kSysExMessage) {
+ // Blink running in a renderer checks permission to raise a SecurityError in
+ // JavaScript. The actual permission check for security perposes happens
+ // here in the browser process.
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
+ renderer_process_id_)) {
+ RecordAction(UserMetricsAction("BadMessageTerminate_MIDI"));
+ BadMessageReceived();
return;
+ }
+ }
-#if defined(OS_ANDROID)
- // TODO(toyoshim): figure out why data() method does not compile on Android.
- NOTIMPLEMENTED();
-#else
midi_manager_->DispatchSendMIDIData(
this,
port,
- data.data(),
- data.size(),
+ data,
timestamp);
-#endif
sent_bytes_in_flight_ += data.size();
}
void MIDIHost::ReceiveMIDIData(
- int port_index,
+ uint32 port,
const uint8* data,
size_t length,
double timestamp) {
TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
- // For now disallow all System Exclusive messages even if we
- // have permission.
- // TODO(toyoshim): allow System Exclusive if browser has granted
- // this client access. We'll likely need to pass a GURL
- // here to compare against our permissions.
- if (length > 0 && data[0] >= kSysExMessage)
+ // Check a process security policy to receive a system exclusive message.
+ if (length > 0 && data[0] >= kSysExMessage) {
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
+ renderer_process_id_)) {
+ // MIDI devices may send a system exclusive messages even if the renderer
+ // doesn't have a permission to receive it. Don't kill the renderer as
+ // OnSendData() does.
return;
+ }
+ }
// Send to the renderer.
std::vector<uint8> v(data, data + length);
- Send(new MIDIMsg_DataReceived(port_index, v, timestamp));
+ Send(new MIDIMsg_DataReceived(port, v, timestamp));
}
void MIDIHost::AccumulateMIDIBytesSent(size_t n) {
diff --git a/chromium/content/browser/renderer_host/media/midi_host.h b/chromium/content/browser/renderer_host/media/midi_host.h
index f6b2813264e..944325d99a0 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.h
+++ b/chromium/content/browser/renderer_host/media/midi_host.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
+#include <vector>
+
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
@@ -23,7 +25,7 @@ class CONTENT_EXPORT MIDIHost
public media::MIDIManagerClient {
public:
// Called from UI thread from the owner of this object.
- MIDIHost(media::MIDIManager* midi_manager);
+ MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -33,7 +35,7 @@ class CONTENT_EXPORT MIDIHost
// MIDIManagerClient implementation.
virtual void ReceiveMIDIData(
- int port_index,
+ uint32 port,
const uint8* data,
size_t length,
double timestamp) OVERRIDE;
@@ -43,7 +45,7 @@ class CONTENT_EXPORT MIDIHost
void OnStartSession(int client_id);
// Data to be sent to a MIDI output port.
- void OnSendData(int port,
+ void OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp);
@@ -53,6 +55,8 @@ class CONTENT_EXPORT MIDIHost
virtual ~MIDIHost();
+ int renderer_process_id_;
+
// |midi_manager_| talks to the platform-specific MIDI APIs.
// It can be NULL if the platform (or our current implementation)
// does not support MIDI. If not supported then a call to
diff --git a/chromium/content/browser/renderer_host/media/mock_media_observer.h b/chromium/content/browser/renderer_host/media/mock_media_observer.h
index fc3734744ea..5f7fb847b3c 100644
--- a/chromium/content/browser/renderer_host/media/mock_media_observer.h
+++ b/chromium/content/browser/renderer_host/media/mock_media_observer.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "content/browser/media/media_internals.h"
#include "content/public/browser/media_observer.h"
+#include "media/audio/audio_parameters.h"
#include "media/base/media_log_event.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -47,6 +48,10 @@ class MockMediaInternals : public MediaInternals {
void(void* host, int stream_id));
MOCK_METHOD3(OnSetAudioStreamPlaying,
void(void* host, int stream_id, bool playing));
+ MOCK_METHOD4(OnAudioStreamCreated,
+ void(void* host, int stream_id,
+ const media::AudioParameters& params,
+ const std::string& input_device_id));
MOCK_METHOD3(OnSetAudioStreamStatus,
void(void* host, int stream_id, const std::string& status));
MOCK_METHOD3(OnSetAudioStreamVolume,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index 207f86a99f3..3e30834feb2 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -128,8 +128,12 @@ int VideoCaptureBufferPool::RecognizeReservedBuffer(
scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame(
const gfx::Size& size,
int rotation) {
- if (static_cast<size_t>(size.GetArea() * 3 / 2) != GetMemorySize())
+ if (GetMemorySize() !=
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, size)) {
+ DCHECK_EQ(GetMemorySize(),
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, size));
return NULL;
+ }
base::AutoLock lock(lock_);
@@ -151,6 +155,7 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame(
gfx::Rect(size),
size,
static_cast<uint8*>(buffer->shared_memory.memory()),
+ GetMemorySize(),
buffer->shared_memory.handle(),
base::TimeDelta(),
disposal_handler);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
index 67a8be4c761..30509a34c75 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -21,8 +21,8 @@ TEST(VideoCaptureBufferPoolTest, BufferPool) {
scoped_refptr<media::VideoFrame> non_pool_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size,
gfx::Rect(size), size, base::TimeDelta());
- scoped_refptr<VideoCaptureBufferPool> pool =
- new VideoCaptureBufferPool(size.GetArea() * 3 / 2, 3);
+ scoped_refptr<VideoCaptureBufferPool> pool = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, size), 3);
ASSERT_EQ(460800u, pool->GetMemorySize());
ASSERT_TRUE(pool->Allocate());
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index bac43289a21..687a21a4996 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -7,6 +7,7 @@
#include <set>
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
@@ -22,6 +23,7 @@
namespace {
+#if defined(OS_IOS) || defined(OS_ANDROID)
// TODO(wjia): Support stride.
void RotatePackedYV12Frame(
const uint8* src,
@@ -43,6 +45,7 @@ void RotatePackedYV12Frame(
media::RotatePlaneByPixels(
src, dest_vplane, width/2, height/2, rotation, flip_vert, flip_horiz);
}
+#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
} // namespace
@@ -77,31 +80,109 @@ struct VideoCaptureController::ControllerClient {
// Buffers used by this client.
std::set<int> buffers;
- // State of capture session, controlled by VideoCaptureManager directly.
+ // State of capture session, controlled by VideoCaptureManager directly. This
+ // transitions to true as soon as StopSession() occurs, at which point the
+ // client is sent an OnEnded() event. However, because the client retains a
+ // VideoCaptureController* pointer, its ControllerClient entry lives on until
+ // it unregisters itself via RemoveClient(), which may happen asynchronously.
+ //
+ // TODO(nick): If we changed the semantics of VideoCaptureHost so that
+ // OnEnded() events were processed synchronously (with the RemoveClient() done
+ // implicitly), we could avoid tracking this state here in the Controller, and
+ // simplify the code in both places.
bool session_closed;
};
-VideoCaptureController::VideoCaptureController(
- VideoCaptureManager* video_capture_manager)
- : chopped_width_(0),
- chopped_height_(0),
- frame_info_available_(false),
- video_capture_manager_(video_capture_manager),
- device_in_use_(false),
- state_(VIDEO_CAPTURE_STATE_STOPPED) {
+// Receives events from the VideoCaptureDevice and posts them to a
+// VideoCaptureController on the IO thread. An instance of this class may safely
+// outlive its target VideoCaptureController.
+//
+// Methods of this class may be called from any thread, and in practice will
+// often be called on some auxiliary thread depending on the platform and the
+// device type; including, for example, the DirectShow thread on Windows, the
+// v4l2_thread on Linux, and the UI thread for tab capture.
+class VideoCaptureController::VideoCaptureDeviceClient
+ : public media::VideoCaptureDevice::EventHandler {
+ public:
+ explicit VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller);
+ virtual ~VideoCaptureDeviceClient();
+
+ // VideoCaptureDevice::EventHandler implementation.
+ virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE;
+ virtual void OnIncomingCapturedFrame(const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ bool flip_vert,
+ bool flip_horiz) OVERRIDE;
+ virtual void OnIncomingCapturedVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::Time timestamp) OVERRIDE;
+ virtual void OnError() OVERRIDE;
+ virtual void OnFrameInfo(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+ virtual void OnFrameInfoChanged(
+ const media::VideoCaptureCapability& info) OVERRIDE;
+
+ private:
+ // The controller to which we post events.
+ const base::WeakPtr<VideoCaptureController> controller_;
+
+ // The pool of shared-memory buffers used for capturing.
+ scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
+
+ // Chopped pixels in width/height in case video capture device has odd
+ // numbers for width/height.
+ int chopped_width_;
+ int chopped_height_;
+
+ // Tracks the current frame format.
+ media::VideoCaptureCapability frame_info_;
+
+ // For NV21 we have to do color conversion into the intermediate buffer and
+ // from there the rotations. This variable won't be needed after
+ // http://crbug.com/292400
+#if defined(OS_IOS) || defined(OS_ANDROID)
+ scoped_ptr<uint8[]> i420_intermediate_buffer_;
+#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
+};
+
+VideoCaptureController::VideoCaptureController()
+ : state_(VIDEO_CAPTURE_STATE_STARTED),
+ weak_ptr_factory_(this) {
memset(&current_params_, 0, sizeof(current_params_));
}
-void VideoCaptureController::StartCapture(
+VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
+ const base::WeakPtr<VideoCaptureController>& controller)
+ : controller_(controller),
+ chopped_width_(0),
+ chopped_height_(0) {}
+
+VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
+
+base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+scoped_ptr<media::VideoCaptureDevice::EventHandler>
+VideoCaptureController::NewDeviceClient() {
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> result(
+ new VideoCaptureDeviceClient(this->GetWeakPtr()));
+ return result.Pass();
+}
+
+void VideoCaptureController::AddClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
base::ProcessHandle render_process,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureController::StartCapture, id " << id.device_id
+ DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
<< ", (" << params.width
<< ", " << params.height
- << ", " << params.frame_per_second
+ << ", " << params.frame_rate
<< ", " << params.session_id
<< ")";
@@ -111,71 +192,32 @@ void VideoCaptureController::StartCapture(
return;
}
- // Do nothing if this client has called StartCapture before.
- if (FindClient(id, event_handler, controller_clients_) ||
- FindClient(id, event_handler, pending_clients_))
+ // Do nothing if this client has called AddClient before.
+ if (FindClient(id, event_handler, controller_clients_))
return;
ControllerClient* client = new ControllerClient(id, event_handler,
render_process, params);
- // In case capture has been started, need to check different conditions.
+ // If we already have gotten frame_info from the device, repeat it to the new
+ // client.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- // TODO(wjia): Temporarily disable restarting till client supports resampling.
-#if 0
- // This client has higher resolution than what is currently requested.
- // Need restart capturing.
- if (params.width > current_params_.width ||
- params.height > current_params_.height) {
- video_capture_manager_->Stop(current_params_.session_id,
- base::Bind(&VideoCaptureController::OnDeviceStopped, this));
- frame_info_available_ = false;
- state_ = VIDEO_CAPTURE_STATE_STOPPING;
- pending_clients_.push_back(client);
- return;
- }
-#endif
-
- // This client's resolution is no larger than what's currently requested.
- // When frame_info has been returned by device, send them to client.
- if (frame_info_available_) {
+ if (frame_info_.IsValid()) {
SendFrameInfoAndBuffers(client);
}
controller_clients_.push_back(client);
return;
}
-
- // In case the device is in the middle of stopping, put the client in
- // pending queue.
- if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- pending_clients_.push_back(client);
- return;
- }
-
- // Fresh start.
- controller_clients_.push_back(client);
- current_params_ = params;
- // Order the manager to start the actual capture.
- video_capture_manager_->Start(params, this);
- state_ = VIDEO_CAPTURE_STATE_STARTED;
- device_in_use_ = true;
}
-void VideoCaptureController::StopCapture(
+int VideoCaptureController::RemoveClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id;
+ DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
- ControllerClient* client = FindClient(id, event_handler, pending_clients_);
- // If the client is still in pending queue, just remove it.
- if (client) {
- pending_clients_.remove(client);
- return;
- }
-
- client = FindClient(id, event_handler, controller_clients_);
+ ControllerClient* client = FindClient(id, event_handler, controller_clients_);
if (!client)
- return;
+ return kInvalidMediaCaptureSessionId;
// Take back all buffers held by the |client|.
if (buffer_pool_.get()) {
@@ -189,28 +231,17 @@ void VideoCaptureController::StopCapture(
client->buffers.clear();
int session_id = client->parameters.session_id;
- delete client;
controller_clients_.remove(client);
+ delete client;
- // No more clients. Stop device.
- if (controller_clients_.empty() &&
- (state_ == VIDEO_CAPTURE_STATE_STARTED ||
- state_ == VIDEO_CAPTURE_STATE_ERROR)) {
- video_capture_manager_->Stop(session_id,
- base::Bind(&VideoCaptureController::OnDeviceStopped, this));
- frame_info_available_ = false;
- state_ = VIDEO_CAPTURE_STATE_STOPPING;
- }
+ return session_id;
}
-void VideoCaptureController::StopSession(
- int session_id) {
+void VideoCaptureController::StopSession(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
- ControllerClient* client = FindClient(session_id, pending_clients_);
- if (!client)
- client = FindClient(session_id, controller_clients_);
+ ControllerClient* client = FindClient(session_id, controller_clients_);
if (client) {
client->session_closed = true;
@@ -224,59 +255,174 @@ void VideoCaptureController::ReturnBuffer(
int buffer_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ControllerClient* client = FindClient(id, event_handler,
- controller_clients_);
+ ControllerClient* client = FindClient(id, event_handler, controller_clients_);
// If this buffer is not held by this client, or this client doesn't exist
// in controller, do nothing.
if (!client ||
- client->buffers.find(buffer_id) == client->buffers.end())
+ client->buffers.find(buffer_id) == client->buffers.end()) {
+ NOTREACHED();
return;
+ }
client->buffers.erase(buffer_id);
buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
-
- // When all buffers have been returned by clients and device has been
- // called to stop, check if restart is needed. This could happen when
- // capture needs to be restarted due to resolution change.
- if (!buffer_pool_->IsAnyBufferHeldForConsumers() &&
- state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- PostStopping();
- }
}
-scoped_refptr<media::VideoFrame> VideoCaptureController::ReserveOutputBuffer() {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return NULL;
+scoped_refptr<media::VideoFrame>
+VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() {
return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
frame_info_.height),
0);
}
-// Implements VideoCaptureDevice::EventHandler.
-// OnIncomingCapturedFrame is called the thread running the capture device.
-// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
-void VideoCaptureController::OnIncomingCapturedFrame(
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
const uint8* data,
int length,
base::Time timestamp,
int rotation,
bool flip_vert,
bool flip_horiz) {
- DCHECK(frame_info_.color == media::VideoCaptureCapability::kI420 ||
- frame_info_.color == media::VideoCaptureCapability::kYV12 ||
- (rotation == 0 && !flip_vert && !flip_horiz));
+ TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
- scoped_refptr<media::VideoFrame> dst;
- {
- base::AutoLock lock(buffer_pool_lock_);
- if (!buffer_pool_.get())
- return;
- dst = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- rotation);
+ if (!buffer_pool_.get())
+ return;
+ scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame(
+ gfx::Size(frame_info_.width, frame_info_.height), rotation);
+
+ if (!dst.get())
+ return;
+
+ uint8* yplane = dst->data(media::VideoFrame::kYPlane);
+ uint8* uplane = dst->data(media::VideoFrame::kUPlane);
+ uint8* vplane = dst->data(media::VideoFrame::kVPlane);
+ int yplane_stride = frame_info_.width;
+ int uv_plane_stride = (frame_info_.width + 1) / 2;
+ int crop_x = 0;
+ int crop_y = 0;
+ libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY;
+ // Assuming rotation happens first and flips next, we can consolidate both
+ // vertical and horizontal flips together with rotation into two variables:
+ // new_rotation = (rotation + 180 * vertical_flip) modulo 360
+ // new_vertical_flip = horizontal_flip XOR vertical_flip
+ int new_rotation_angle = (rotation + 180 * flip_vert) % 360;
+ libyuv::RotationMode rotation_mode = libyuv::kRotate0;
+ if (new_rotation_angle == 90)
+ rotation_mode = libyuv::kRotate90;
+ else if (new_rotation_angle == 180)
+ rotation_mode = libyuv::kRotate180;
+ else if (new_rotation_angle == 270)
+ rotation_mode = libyuv::kRotate270;
+
+ switch (frame_info_.color) {
+ case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
+ break;
+ case media::PIXEL_FORMAT_I420:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_I420;
+ break;
+ case media::PIXEL_FORMAT_YV12:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_YV12;
+ break;
+ case media::PIXEL_FORMAT_NV21:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_NV12;
+ break;
+ case media::PIXEL_FORMAT_YUY2:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_YUY2;
+ break;
+ case media::PIXEL_FORMAT_UYVY:
+ DCHECK(!chopped_width_ && !chopped_height_);
+ origin_colorspace = libyuv::FOURCC_UYVY;
+ break;
+ case media::PIXEL_FORMAT_RGB24:
+ origin_colorspace = libyuv::FOURCC_RAW;
+ break;
+ case media::PIXEL_FORMAT_ARGB:
+ origin_colorspace = libyuv::FOURCC_ARGB;
+ break;
+ case media::PIXEL_FORMAT_MJPEG:
+ origin_colorspace = libyuv::FOURCC_MJPG;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ int need_convert_rgb24_on_win = false;
+#if defined(OS_WIN)
+ // kRGB24 on Windows start at the bottom line and has a negative stride. This
+ // is not supported by libyuv, so the media API is used instead.
+ if (frame_info_.color == media::PIXEL_FORMAT_RGB24) {
+ // Rotation and flipping is not supported in kRGB24 and OS_WIN case.
+ DCHECK(!rotation && !flip_vert && !flip_horiz);
+ need_convert_rgb24_on_win = true;
}
+#endif
+ if (need_convert_rgb24_on_win) {
+ int rgb_stride = -3 * (frame_info_.width + chopped_width_);
+ const uint8* rgb_src =
+ data + 3 * (frame_info_.width + chopped_width_) *
+ (frame_info_.height - 1 + chopped_height_);
+ media::ConvertRGB24ToYUV(rgb_src,
+ yplane,
+ uplane,
+ vplane,
+ frame_info_.width,
+ frame_info_.height,
+ rgb_stride,
+ yplane_stride,
+ uv_plane_stride);
+ } else {
+ libyuv::ConvertToI420(
+ data,
+ length,
+ yplane,
+ yplane_stride,
+ uplane,
+ uv_plane_stride,
+ vplane,
+ uv_plane_stride,
+ crop_x,
+ crop_y,
+ frame_info_.width + chopped_width_,
+ frame_info_.height * (flip_vert ^ flip_horiz ? -1 : 1),
+ frame_info_.width,
+ frame_info_.height,
+ rotation_mode,
+ origin_colorspace);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
+ controller_,
+ dst,
+ timestamp));
+}
+#else
+void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
+ const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ bool flip_vert,
+ bool flip_horiz) {
+ DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 ||
+ frame_info_.color == media::PIXEL_FORMAT_YV12 ||
+ frame_info_.color == media::PIXEL_FORMAT_NV21 ||
+ (rotation == 0 && !flip_vert && !flip_horiz));
+
+ TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
+
+ if (!buffer_pool_)
+ return;
+ scoped_refptr<media::VideoFrame> dst =
+ buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
+ frame_info_.height),
+ rotation);
if (!dst.get())
return;
@@ -287,26 +433,36 @@ void VideoCaptureController::OnIncomingCapturedFrame(
// Do color conversion from the camera format to I420.
switch (frame_info_.color) {
- case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
+ case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
break;
- case media::VideoCaptureCapability::kI420:
+ case media::PIXEL_FORMAT_I420:
DCHECK(!chopped_width_ && !chopped_height_);
RotatePackedYV12Frame(
data, yplane, uplane, vplane, frame_info_.width, frame_info_.height,
rotation, flip_vert, flip_horiz);
break;
- case media::VideoCaptureCapability::kYV12:
+ case media::PIXEL_FORMAT_YV12:
DCHECK(!chopped_width_ && !chopped_height_);
RotatePackedYV12Frame(
data, yplane, vplane, uplane, frame_info_.width, frame_info_.height,
rotation, flip_vert, flip_horiz);
break;
- case media::VideoCaptureCapability::kNV21:
+ case media::PIXEL_FORMAT_NV21: {
DCHECK(!chopped_width_ && !chopped_height_);
- media::ConvertNV21ToYUV(data, yplane, uplane, vplane, frame_info_.width,
+ int num_pixels = frame_info_.width * frame_info_.height;
+ media::ConvertNV21ToYUV(data,
+ &i420_intermediate_buffer_[0],
+ &i420_intermediate_buffer_[num_pixels],
+ &i420_intermediate_buffer_[num_pixels * 5 / 4],
+ frame_info_.width,
frame_info_.height);
- break;
- case media::VideoCaptureCapability::kYUY2:
+ RotatePackedYV12Frame(
+ i420_intermediate_buffer_.get(), yplane, uplane, vplane,
+ frame_info_.width, frame_info_.height,
+ rotation, flip_vert, flip_horiz);
+ break;
+ }
+ case media::PIXEL_FORMAT_YUY2:
DCHECK(!chopped_width_ && !chopped_height_);
if (frame_info_.width * frame_info_.height * 2 != length) {
// If |length| of |data| does not match the expected width and height
@@ -317,42 +473,22 @@ void VideoCaptureController::OnIncomingCapturedFrame(
media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
frame_info_.height);
break;
- case media::VideoCaptureCapability::kRGB24: {
+ case media::PIXEL_FORMAT_RGB24: {
int ystride = frame_info_.width;
int uvstride = frame_info_.width / 2;
-#if defined(OS_WIN) // RGB on Windows start at the bottom line.
- int rgb_stride = -3 * (frame_info_.width + chopped_width_);
- const uint8* rgb_src = data + 3 * (frame_info_.width + chopped_width_) *
- (frame_info_.height -1 + chopped_height_);
-#else
int rgb_stride = 3 * (frame_info_.width + chopped_width_);
const uint8* rgb_src = data;
-#endif
media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
frame_info_.width, frame_info_.height,
rgb_stride, ystride, uvstride);
break;
}
- case media::VideoCaptureCapability::kARGB:
+ case media::PIXEL_FORMAT_ARGB:
media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width,
frame_info_.height,
(frame_info_.width + chopped_width_) * 4,
frame_info_.width, frame_info_.width / 2);
break;
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
- case media::VideoCaptureCapability::kMJPEG: {
- int yplane_stride = frame_info_.width;
- int uv_plane_stride = (frame_info_.width + 1) / 2;
- int crop_x = 0;
- int crop_y = 0;
- libyuv::ConvertToI420(data, length, yplane, yplane_stride, uplane,
- uv_plane_stride, vplane, uv_plane_stride, crop_x,
- crop_y, frame_info_.width, frame_info_.height,
- frame_info_.width, frame_info_.height,
- libyuv::kRotate0, libyuv::FOURCC_MJPG);
- break;
- }
-#endif
default:
NOTREACHED();
}
@@ -360,38 +496,35 @@ void VideoCaptureController::OnIncomingCapturedFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, dst, timestamp));
+ controller_, dst, timestamp));
}
+#endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
-// OnIncomingCapturedVideoFrame is called the thread running the capture device.
-void VideoCaptureController::OnIncomingCapturedVideoFrame(
+void
+VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
const scoped_refptr<media::VideoFrame>& frame,
base::Time timestamp) {
+ if (!buffer_pool_)
+ return;
- scoped_refptr<media::VideoFrame> target;
- {
- base::AutoLock lock(buffer_pool_lock_);
-
- if (!buffer_pool_.get())
- return;
-
- // If this is a frame that belongs to the buffer pool, we can forward it
- // directly to the IO thread and be done.
- if (buffer_pool_->RecognizeReservedBuffer(
- frame->shared_memory_handle()) >= 0) {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, frame, timestamp));
- return;
- }
- // Otherwise, this is a frame that belongs to the caller, and we must copy
- // it to a frame from the buffer pool.
- target = buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- 0);
+ // If this is a frame that belongs to the buffer pool, we can forward it
+ // directly to the IO thread and be done.
+ if (buffer_pool_->RecognizeReservedBuffer(
+ frame->shared_memory_handle()) >= 0) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
+ controller_, frame, timestamp));
+ return;
}
+ // Otherwise, this is a frame that belongs to the caller, and we must copy
+ // it to a frame from the buffer pool.
+ scoped_refptr<media::VideoFrame> target =
+ buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
+ frame_info_.height),
+ 0);
+
if (!target.get())
return;
@@ -478,18 +611,18 @@ void VideoCaptureController::OnIncomingCapturedVideoFrame(
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- this, target, timestamp));
+ controller_, target, timestamp));
}
-void VideoCaptureController::OnError() {
+void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
}
-void VideoCaptureController::OnFrameInfo(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
const media::VideoCaptureCapability& info) {
- frame_info_= info;
+ frame_info_ = info;
// Handle cases when |info| has odd numbers for width/height.
if (info.width & 1) {
--frame_info_.width;
@@ -503,32 +636,51 @@ void VideoCaptureController::OnFrameInfo(
} else {
chopped_height_ = 0;
}
+#if defined(OS_IOS) || defined(OS_ANDROID)
+ if (frame_info_.color == media::PIXEL_FORMAT_NV21 &&
+ !i420_intermediate_buffer_) {
+ i420_intermediate_buffer_.reset(
+ new uint8[frame_info_.width * frame_info_.height * 12 / 8]);
+ }
+#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
+
+ DCHECK(!buffer_pool_.get());
+
+ // TODO(nick): Give BufferPool the same lifetime as the controller, have it
+ // support frame size changes, and stop checking it for NULL everywhere.
+ // http://crbug.com/266082
+ buffer_pool_ = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(
+ media::VideoFrame::I420,
+ gfx::Size(frame_info_.width, frame_info_.height)),
+ kNoOfBuffers);
+
+ // Check whether all buffers were created successfully.
+ if (!buffer_pool_->Allocate()) {
+ // Transition to the error state.
+ buffer_pool_ = NULL;
+ OnError();
+ return;
+ }
+
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this));
+ base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
+ frame_info_, buffer_pool_));
}
-void VideoCaptureController::OnFrameInfoChanged(
+void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
const media::VideoCaptureCapability& info) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread,
- this, info));
+ controller_, info));
}
VideoCaptureController::~VideoCaptureController() {
buffer_pool_ = NULL; // Release all buffers.
STLDeleteContainerPointers(controller_clients_.begin(),
controller_clients_.end());
- STLDeleteContainerPointers(pending_clients_.begin(),
- pending_clients_.end());
-}
-
-// Called by VideoCaptureManager when a device have been stopped.
-void VideoCaptureController::OnDeviceStopped() {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this));
}
void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
@@ -563,37 +715,24 @@ void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
buffer_pool_->HoldForConsumers(buffer_id, count);
}
-void VideoCaptureController::DoFrameInfoOnIOThread() {
+void VideoCaptureController::DoFrameInfoOnIOThread(
+ const media::VideoCaptureCapability& frame_info,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!buffer_pool_.get())
- << "Device is restarted without releasing shared memory.";
+ DCHECK(!buffer_pool_.get()) << "Frame info should happen only once.";
// Allocate memory only when device has been started.
if (state_ != VIDEO_CAPTURE_STATE_STARTED)
return;
- scoped_refptr<VideoCaptureBufferPool> buffer_pool =
- new VideoCaptureBufferPool(frame_info_.width * frame_info_.height * 3 / 2,
- kNoOfBuffers);
-
- // Check whether all buffers were created successfully.
- if (!buffer_pool->Allocate()) {
- state_ = VIDEO_CAPTURE_STATE_ERROR;
- for (ControllerClients::iterator client_it = controller_clients_.begin();
- client_it != controller_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
- return;
- }
-
- {
- base::AutoLock lock(buffer_pool_lock_);
- buffer_pool_ = buffer_pool;
- }
- frame_info_available_ = true;
+ frame_info_ = frame_info;
+ buffer_pool_ = buffer_pool;
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
+ if ((*client_it)->session_closed)
+ continue;
+
SendFrameInfoAndBuffers(*client_it);
}
}
@@ -605,6 +744,9 @@ void VideoCaptureController::DoFrameInfoChangedOnIOThread(
// needed, to support the new video capture format. See crbug.com/266082.
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
+ if ((*client_it)->session_closed)
+ continue;
+
(*client_it)->event_handler->OnFrameInfoChanged(
(*client_it)->controller_id,
info.width,
@@ -619,25 +761,16 @@ void VideoCaptureController::DoErrorOnIOThread() {
ControllerClients::iterator client_it;
for (client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
- for (client_it = pending_clients_.begin();
- client_it != pending_clients_.end(); ++client_it) {
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
-}
+ if ((*client_it)->session_closed)
+ continue;
-void VideoCaptureController::DoDeviceStoppedOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_in_use_ = false;
- if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- PostStopping();
+ (*client_it)->event_handler->OnError((*client_it)->controller_id);
}
}
void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(frame_info_available_);
+ DCHECK(frame_info_.IsValid());
client->event_handler->OnFrameInfo(client->controller_id,
frame_info_);
for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {
@@ -679,54 +812,9 @@ VideoCaptureController::FindClient(
return NULL;
}
-// This function is called when all buffers have been returned to controller,
-// or when device is stopped. It decides whether the device needs to be
-// restarted.
-void VideoCaptureController::PostStopping() {
+int VideoCaptureController::GetClientCount() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPING);
-
- // When clients still have some buffers, or device has not been stopped yet,
- // do nothing.
- if ((buffer_pool_.get() && buffer_pool_->IsAnyBufferHeldForConsumers()) ||
- device_in_use_)
- return;
-
- {
- base::AutoLock lock(buffer_pool_lock_);
- buffer_pool_ = NULL;
- }
-
- // No more client. Therefore the controller is stopped.
- if (controller_clients_.empty() && pending_clients_.empty()) {
- state_ = VIDEO_CAPTURE_STATE_STOPPED;
- return;
- }
-
- // Restart the device.
- current_params_.width = 0;
- current_params_.height = 0;
- ControllerClients::iterator client_it;
- for (client_it = controller_clients_.begin();
- client_it != controller_clients_.end(); ++client_it) {
- if (current_params_.width < (*client_it)->parameters.width)
- current_params_.width = (*client_it)->parameters.width;
- if (current_params_.height < (*client_it)->parameters.height)
- current_params_.height = (*client_it)->parameters.height;
- }
- for (client_it = pending_clients_.begin();
- client_it != pending_clients_.end(); ) {
- if (current_params_.width < (*client_it)->parameters.width)
- current_params_.width = (*client_it)->parameters.width;
- if (current_params_.height < (*client_it)->parameters.height)
- current_params_.height = (*client_it)->parameters.height;
- controller_clients_.push_back((*client_it));
- pending_clients_.erase(client_it++);
- }
- // Request the manager to start the actual capture.
- video_capture_manager_->Start(current_params_, this);
- state_ = VIDEO_CAPTURE_STATE_STARTED;
- device_in_use_ = true;
+ return controller_clients_.size();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.h b/chromium/content/browser/renderer_host/media/video_capture_controller.h
index 5d33d01163c..eda4ce31e01 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -1,17 +1,48 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
-// VideoCaptureController is the glue between VideoCaptureHost,
-// VideoCaptureManager and VideoCaptureDevice.
-// It provides functions for VideoCaptureHost to start a VideoCaptureDevice and
-// is responsible for keeping track of shared DIBs and filling them with I420
-// video frames for IPC communication between VideoCaptureHost and
-// VideoCaptureMessageFilter.
-// It implements media::VideoCaptureDevice::EventHandler to get video frames
-// from a VideoCaptureDevice object and do color conversion straight into the
-// shared DIBs to avoid a memory copy.
-// It serves multiple VideoCaptureControllerEventHandlers.
+//
+// VideoCaptureController is the glue between a VideoCaptureDevice and all
+// VideoCaptureHosts that have connected to it. A controller exists on behalf of
+// one (and only one) VideoCaptureDevice; both are owned by the
+// VideoCaptureManager.
+//
+// The VideoCaptureController is responsible for:
+//
+// * Allocating and keeping track of shared memory buffers, and filling them
+// with I420 video frames for IPC communication between VideoCaptureHost (in
+// the browser process) and VideoCaptureMessageFilter (in the renderer
+// process).
+// * Broadcasting the events from a single VideoCaptureDevice, fanning them
+// out to multiple clients.
+// * Keeping track of the clients on behalf of the VideoCaptureManager, making
+// it possible for the Manager to delete the Controller and its Device when
+// there are no clients left.
+//
+// A helper class, VCC::VideoCaptureDeviceClient, is responsible for:
+//
+// * Conveying events from the device thread (where VideoCaptureDevices live)
+// the IO thread (where the VideoCaptureController lives).
+// * Performing some image transformations on the output of the Device;
+// specifically, colorspace conversion and rotation.
+//
+// Interactions between VideoCaptureController and other classes:
+//
+// * VideoCaptureController indirectly observes a VideoCaptureDevice
+// by means of its proxy, VideoCaptureDeviceClient, which implements
+// the VideoCaptureDevice::EventHandler interface. The proxy forwards
+// observed events to the VideoCaptureController on the IO thread.
+// * A VideoCaptureController interacts with its clients (VideoCaptureHosts)
+// via the VideoCaptureControllerEventHandler interface.
+// * Conversely, a VideoCaptureControllerEventHandler (typically,
+// VideoCaptureHost) will interact directly with VideoCaptureController to
+// return leased buffers by means of the ReturnBuffer() public method of
+// VCC.
+// * VideoCaptureManager (which owns the VCC) interacts directly with
+// VideoCaptureController through its public methods, to add and remove
+// clients.
+//
+// VideoCaptureController is not thread safe and operates on the IO thread only.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
@@ -21,6 +52,8 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/synchronization/lock.h"
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
@@ -32,31 +65,37 @@
#include "media/video/capture/video_capture_types.h"
namespace content {
-class VideoCaptureManager;
class VideoCaptureBufferPool;
-class CONTENT_EXPORT VideoCaptureController
- : public base::RefCountedThreadSafe<VideoCaptureController>,
- public media::VideoCaptureDevice::EventHandler {
+class CONTENT_EXPORT VideoCaptureController {
public:
- VideoCaptureController(VideoCaptureManager* video_capture_manager);
+ VideoCaptureController();
+ virtual ~VideoCaptureController();
+
+ base::WeakPtr<VideoCaptureController> GetWeakPtr();
+
+ // Return a new VideoCaptureDeviceClient to forward capture events to this
+ // instance.
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> NewDeviceClient();
// Start video capturing and try to use the resolution specified in
// |params|.
- // When capturing has started, the |event_handler| receives a call OnFrameInfo
- // with resolution that best matches the requested that the video
- // capture device support.
- void StartCapture(const VideoCaptureControllerID& id,
- VideoCaptureControllerEventHandler* event_handler,
- base::ProcessHandle render_process,
- const media::VideoCaptureParams& params);
-
- // Stop video capture.
- // This will take back all buffers held by by |event_handler|, and
- // |event_handler| shouldn't use those buffers any more.
- void StopCapture(const VideoCaptureControllerID& id,
+ // When capturing starts, the |event_handler| will receive an OnFrameInfo()
+ // call informing it of the resolution that was actually picked by the device.
+ void AddClient(const VideoCaptureControllerID& id,
+ VideoCaptureControllerEventHandler* event_handler,
+ base::ProcessHandle render_process,
+ const media::VideoCaptureParams& params);
+
+ // Stop video capture. This will take back all buffers held by by
+ // |event_handler|, and |event_handler| shouldn't use those buffers any more.
+ // Returns the session_id of the stopped client, or
+ // kInvalidMediaCaptureSessionId if the indicated client was not registered.
+ int RemoveClient(const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler);
+ int GetClientCount();
+
// API called directly by VideoCaptureManager in case the device is
// prematurely closed.
void StopSession(int session_id);
@@ -67,39 +106,19 @@ class CONTENT_EXPORT VideoCaptureController
VideoCaptureControllerEventHandler* event_handler,
int buffer_id);
- // Implement media::VideoCaptureDevice::EventHandler.
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE;
- virtual void OnIncomingCapturedFrame(const uint8* data,
- int length,
- base::Time timestamp,
- int rotation,
- bool flip_vert,
- bool flip_horiz) OVERRIDE;
- virtual void OnIncomingCapturedVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp) OVERRIDE;
- virtual void OnError() OVERRIDE;
- virtual void OnFrameInfo(const media::VideoCaptureCapability& info) OVERRIDE;
- virtual void OnFrameInfoChanged(
- const media::VideoCaptureCapability& info) OVERRIDE;
-
- protected:
- virtual ~VideoCaptureController();
-
private:
- friend class base::RefCountedThreadSafe<VideoCaptureController>;
+ class VideoCaptureDeviceClient;
struct ControllerClient;
typedef std::list<ControllerClient*> ControllerClients;
- // Callback when manager has stopped device.
- void OnDeviceStopped();
-
- // Worker functions on IO thread.
+ // Worker functions on IO thread. Called by the VideoCaptureDeviceClient.
void DoIncomingCapturedFrameOnIOThread(
const scoped_refptr<media::VideoFrame>& captured_frame,
base::Time timestamp);
- void DoFrameInfoOnIOThread();
+ void DoFrameInfoOnIOThread(
+ const media::VideoCaptureCapability& frame_info,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
void DoFrameInfoChangedOnIOThread(const media::VideoCaptureCapability& info);
void DoErrorOnIOThread();
void DoDeviceStoppedOnIOThread();
@@ -118,45 +137,25 @@ class CONTENT_EXPORT VideoCaptureController
int session_id,
const ControllerClients& clients);
- // Decide what to do after kStopping state. Dependent on events, controller
- // can stay in kStopping state, or go to kStopped, or restart capture.
- void PostStopping();
-
- // Protects access to the |buffer_pool_| pointer on non-IO threads. IO thread
- // must hold this lock when modifying the |buffer_pool_| pointer itself.
- // TODO(nick): Make it so that this lock isn't required.
- base::Lock buffer_pool_lock_;
-
// The pool of shared-memory buffers used for capturing.
scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
// All clients served by this controller.
ControllerClients controller_clients_;
- // All clients waiting for service.
- ControllerClients pending_clients_;
-
// The parameter that currently used for the capturing.
media::VideoCaptureParams current_params_;
- // It's modified on caller thread, assuming there is only one OnFrameInfo()
- // call per StartCapture().
+ // Tracks the current frame format.
media::VideoCaptureCapability frame_info_;
- // Chopped pixels in width/height in case video capture device has odd numbers
- // for width/height.
- int chopped_width_;
- int chopped_height_;
-
- // It's accessed only on IO thread.
- bool frame_info_available_;
-
- VideoCaptureManager* video_capture_manager_;
-
- bool device_in_use_;
+ // Takes on only the states 'STARTED' and 'ERROR'. 'ERROR' is an absorbing
+ // state which stops the flow of data to clients.
VideoCaptureState state_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureController);
+ base::WeakPtrFactory<VideoCaptureController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureController);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index c4844af2f73..4a2c294b0ba 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -10,7 +10,7 @@
#include "content/common/content_export.h"
namespace media {
-struct VideoCaptureCapability;
+class VideoCaptureCapability;
}
namespace content {
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index c4b716d2e33..fec0942dde0 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -7,141 +7,74 @@
#include <string>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "content/browser/browser_thread_impl.h"
+#include "base/run_loop.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
+#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
-#include "media/video/capture/fake_video_capture_device.h"
-#include "media/video/capture/video_capture_device.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
+#include "media/video/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::AtLeast;
using ::testing::InSequence;
-using ::testing::Return;
+using ::testing::Mock;
namespace content {
-enum { kDeviceId = 1 };
-
-ACTION_P4(StopCapture, controller, controller_id, controller_handler,
- message_loop) {
- message_loop->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureController::StopCapture,
- controller, controller_id, controller_handler));
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
-ACTION_P3(StopSession, controller, session_id, message_loop) {
- message_loop->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureController::StopSession,
- controller, session_id));
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
class MockVideoCaptureControllerEventHandler
: public VideoCaptureControllerEventHandler {
public:
- MockVideoCaptureControllerEventHandler(VideoCaptureController* controller,
- base::MessageLoop* message_loop)
- : controller_(controller),
- message_loop_(message_loop),
- controller_id_(kDeviceId),
- process_handle_(base::kNullProcessHandle) {
- }
+ explicit MockVideoCaptureControllerEventHandler(
+ VideoCaptureController* controller)
+ : controller_(controller) {}
virtual ~MockVideoCaptureControllerEventHandler() {}
+ // These mock methods are delegated to by our fake implementation of
+ // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoFrameInfo, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
+ MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
- virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {}
+ virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
+ DoError(id);
+ }
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
int length, int buffer_id) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoBufferCreated(id);
}
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
base::Time timestamp) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoBufferReady(id);
- message_loop_->PostTask(FROM_HERE,
+ base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&VideoCaptureController::ReturnBuffer,
- controller_, controller_id_, this, buffer_id));
+ base::Unretained(controller_), id, this, buffer_id));
}
virtual void OnFrameInfo(
const VideoCaptureControllerID& id,
const media::VideoCaptureCapability& format) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoFrameInfo(id);
}
virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
- EXPECT_EQ(id, controller_id_);
DoEnded(id);
+ // OnEnded() must respond by (eventually) unregistering the client.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
+ base::Unretained(controller_), id, this));
}
- scoped_refptr<VideoCaptureController> controller_;
- base::MessageLoop* message_loop_;
- VideoCaptureControllerID controller_id_;
- base::ProcessHandle process_handle_;
-};
-
-class MockVideoCaptureManager : public VideoCaptureManager {
- public:
- MockVideoCaptureManager()
- : video_session_id_(kStartOpenSessionId),
- device_name_("fake_device_0", "/dev/video0") {}
-
- void Init() {
- video_capture_device_.reset(
- media::FakeVideoCaptureDevice::Create(device_name_));
- ASSERT_TRUE(video_capture_device_.get() != NULL);
- }
-
- MOCK_METHOD3(StartCapture, void(int, int,
- media::VideoCaptureDevice::EventHandler*));
- MOCK_METHOD1(StopCapture, void(const media::VideoCaptureSessionId&));
-
- void Start(const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* vc_receiver) OVERRIDE {
- StartCapture(capture_params.width, capture_params.height, vc_receiver);
- // TODO(mcasas): Add testing for variable resolution video capture devices,
- // supported by FakeVideoCaptureDevice. See crbug.com/261410, second part.
- media::VideoCaptureCapability capture_format(
- capture_params.width,
- capture_params.height,
- capture_params.frame_per_second,
- media::VideoCaptureCapability::kI420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- video_capture_device_->Allocate(capture_format, vc_receiver);
- video_capture_device_->Start();
- }
-
- void Stop(const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb) OVERRIDE {
- StopCapture(capture_session_id);
- video_capture_device_->Stop();
- video_capture_device_->DeAllocate();
- }
-
- int video_session_id_;
- media::VideoCaptureDevice::Name device_name_;
- scoped_ptr<media::VideoCaptureDevice> video_capture_device_;
-
- private:
- virtual ~MockVideoCaptureManager() {}
- DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureManager);
+ VideoCaptureController* controller_;
};
// Test class.
@@ -151,115 +84,371 @@ class VideoCaptureControllerTest : public testing::Test {
virtual ~VideoCaptureControllerTest() {}
protected:
+ static const int kPoolSize = 3;
+
virtual void SetUp() OVERRIDE {
- message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
- file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE,
- message_loop_.get()));
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
-
- vcm_ = new MockVideoCaptureManager();
- vcm_->Init();
- controller_ = new VideoCaptureController(vcm_.get());
- controller_handler_.reset(new MockVideoCaptureControllerEventHandler(
- controller_.get(), message_loop_.get()));
+ controller_.reset(new VideoCaptureController());
+ device_ = controller_->NewDeviceClient().Pass();
+ client_a_.reset(new MockVideoCaptureControllerEventHandler(
+ controller_.get()));
+ client_b_.reset(new MockVideoCaptureControllerEventHandler(
+ controller_.get()));
}
- virtual void TearDown() OVERRIDE {}
+ virtual void TearDown() OVERRIDE {
+ base::RunLoop().RunUntilIdle();
+ }
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> file_thread_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
- scoped_refptr<MockVideoCaptureManager> vcm_;
- scoped_ptr<MockVideoCaptureControllerEventHandler> controller_handler_;
- scoped_refptr<VideoCaptureController> controller_;
+ TestBrowserThreadBundle bindle_;
+ scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
+ scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
+ scoped_ptr<VideoCaptureController> controller_;
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> device_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
};
-// Try to start and stop capture.
-TEST_F(VideoCaptureControllerTest, StartAndStop) {
- media::VideoCaptureParams capture_params;
- capture_params.session_id = vcm_->video_session_id_;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
- InSequence s;
- EXPECT_CALL(*vcm_.get(),
- StartCapture(capture_params.width,
- capture_params.height,
- controller_.get())).Times(1);
- EXPECT_CALL(*controller_handler_,
- DoFrameInfo(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferCreated(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(AtLeast(1))
- .WillOnce(StopCapture(controller_.get(),
- controller_handler_->controller_id_,
- controller_handler_.get(),
- message_loop_.get()));
- EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
-
- controller_->StartCapture(controller_handler_->controller_id_,
- controller_handler_.get(),
- controller_handler_->process_handle_,
- capture_params);
- message_loop_->Run();
+// A simple test of VideoCaptureController's ability to add, remove, and keep
+// track of clients.
+TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
+ media::VideoCaptureParams session_100;
+ session_100.session_id = 100;
+ session_100.width = 320;
+ session_100.height = 240;
+ session_100.frame_rate = 30;
+
+ media::VideoCaptureParams session_200 = session_100;
+ session_200.session_id = 200;
+
+ media::VideoCaptureParams session_300 = session_100;
+ session_300.session_id = 300;
+
+ media::VideoCaptureParams session_400 = session_100;
+ session_400.session_id = 400;
+
+ // Intentionally use the same route ID for two of the clients: the device_ids
+ // are a per-VideoCaptureHost namespace, and can overlap across hosts.
+ const VideoCaptureControllerID client_a_route_1(44);
+ const VideoCaptureControllerID client_a_route_2(30);
+ const VideoCaptureControllerID client_b_route_1(30);
+ const VideoCaptureControllerID client_b_route_2(1);
+
+ // Clients in controller: []
+ ASSERT_EQ(0, controller_->GetClientCount())
+ << "Client count should initially be zero.";
+ controller_->AddClient(client_a_route_1, client_a_.get(),
+ base::kNullProcessHandle, session_100);
+ // Clients in controller: [A/1]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Adding client A/1 should bump client count.";;
+ controller_->AddClient(client_a_route_2, client_a_.get(),
+ base::kNullProcessHandle, session_200);
+ // Clients in controller: [A/1, A/2]
+ ASSERT_EQ(2, controller_->GetClientCount())
+ << "Adding client A/2 should bump client count.";
+ controller_->AddClient(client_b_route_1, client_b_.get(),
+ base::kNullProcessHandle, session_300);
+ // Clients in controller: [A/1, A/2, B/1]
+ ASSERT_EQ(3, controller_->GetClientCount())
+ << "Adding client B/1 should bump client count.";
+ ASSERT_EQ(200,
+ controller_->RemoveClient(client_a_route_2, client_a_.get()))
+ << "Removing client A/1 should return its session_id.";
+ // Clients in controller: [A/1, B/1]
+ ASSERT_EQ(2, controller_->GetClientCount());
+ ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
+ controller_->RemoveClient(client_a_route_2, client_a_.get()))
+ << "Removing a nonexistant client should fail.";
+ // Clients in controller: [A/1, B/1]
+ ASSERT_EQ(2, controller_->GetClientCount());
+ ASSERT_EQ(300,
+ controller_->RemoveClient(client_b_route_1, client_b_.get()))
+ << "Removing client B/1 should return its session_id.";
+ // Clients in controller: [A/1]
+ ASSERT_EQ(1, controller_->GetClientCount());
+ controller_->AddClient(client_b_route_2, client_b_.get(),
+ base::kNullProcessHandle, session_400);
+ // Clients in controller: [A/1, B/2]
+
+ EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
+ controller_->StopSession(100); // Session 100 == client A/1
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ ASSERT_EQ(2, controller_->GetClientCount())
+ << "Client should be closed but still exist after StopSession.";
+ // Clients in controller: [A/1 (closed, removal pending), B/2]
+ base::RunLoop().RunUntilIdle();
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Client A/1 should be deleted by now.";
+ controller_->StopSession(200); // Session 200 does not exist anymore
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Stopping non-existant session 200 should be a no-op.";
+ controller_->StopSession(256); // Session 256 never existed.
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Stopping non-existant session 256 should be a no-op.";
+ ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
+ controller_->RemoveClient(client_a_route_1, client_a_.get()))
+ << "Removing already-removed client A/1 should fail.";
+ // Clients in controller: [B/2]
+ ASSERT_EQ(1, controller_->GetClientCount())
+ << "Removing non-existant session 200 should be a no-op.";
+ ASSERT_EQ(400,
+ controller_->RemoveClient(client_b_route_2, client_b_.get()))
+ << "Removing client B/2 should return its session_id.";
+ // Clients in controller: []
+ ASSERT_EQ(0, controller_->GetClientCount())
+ << "Client count should return to zero after all clients are gone.";
+}
+
+// This test will connect and disconnect several clients while simulating an
+// active capture device being started and generating frames. It runs on one
+// thread and is intended to behave deterministically.
+TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
+ media::VideoCaptureParams session_100;
+ session_100.session_id = 100;
+ session_100.width = 320;
+ session_100.height = 240;
+ session_100.frame_rate = 30;
+
+ media::VideoCaptureParams session_200 = session_100;
+ session_200.session_id = 200;
+
+ media::VideoCaptureParams session_300 = session_100;
+ session_300.session_id = 300;
+
+ // session_id of 1 is kStartOpenSessionId, which should have special meaning
+ // to VideoCaptureManager, but not to VideoCaptureController ... so test it.
+ media::VideoCaptureParams session_1 = session_100;
+ session_1.session_id = VideoCaptureManager::kStartOpenSessionId;
+
+ // The device format needn't match the VideoCaptureParams (the camera can do
+ // what it wants). Pick something random to use for OnFrameInfo.
+ media::VideoCaptureCapability device_format(
+ 10, 10, 25, media::PIXEL_FORMAT_RGB24, 10, false,
+ media::ConstantResolutionVideoCaptureDevice);
+
+ const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
+ const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
+ const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1);
+ const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
+
+ // Start with two clients.
+ controller_->AddClient(client_a_route_1, client_a_.get(),
+ base::kNullProcessHandle, session_100);
+ controller_->AddClient(client_b_route_1, client_b_.get(),
+ base::kNullProcessHandle, session_300);
+ ASSERT_EQ(2, controller_->GetClientCount());
+
+ // The OnFrameInfo() event from the device, when processed by the controller,
+ // should generate client OnFrameInfo() and OnBufferCreated() events.
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoFrameInfo(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(kPoolSize);
+ }
+ {
+ InSequence s;
+ EXPECT_CALL(*client_b_, DoFrameInfo(client_b_route_1)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(kPoolSize);
+ }
+ device_->OnFrameInfo(device_format);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // When a third clients is subsequently added, the frame info and buffers
+ // should immediately be shared to the new clients.
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoFrameInfo(client_a_route_2)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(kPoolSize);
+ }
+ controller_->AddClient(client_a_route_2, client_a_.get(),
+ base::kNullProcessHandle, session_200);
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // Now, simulate an incoming captured frame from the capture device.
+ uint8 frame_no = 1;
+ scoped_refptr<media::VideoFrame> frame;
+ frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+ media::FillYUV(frame, frame_no++, 0x22, 0x44);
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ frame = NULL;
+
+ // The buffer should be delivered to the clients in any order.
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // Second frame. In this case pretend that the VideoFrame pointer is held
+ // by the device for a long delay. This shouldn't affect anything.
+ frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+ media::FillYUV(frame, frame_no++, 0x22, 0x44);
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+
+ // The buffer should be delivered to the clients in any order.
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+ frame = NULL;
+
+ // Add a fourth client now that some frames have come through. It should get
+ // the buffer info, but it won't get any frames until new ones are captured.
+ {
+ InSequence s;
+ EXPECT_CALL(*client_b_, DoFrameInfo(client_b_route_2)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
+ }
+ controller_->AddClient(client_b_route_2, client_b_.get(),
+ base::kNullProcessHandle, session_1);
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // Third, fourth, and fifth frames. Pretend they all arrive at the same time.
+ for (int i = 0; i < kPoolSize; i++) {
+ frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+ ASSERT_EQ(media::VideoFrame::I420, frame->format());
+ media::FillYUV(frame, frame_no++, 0x22, 0x44);
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+
+ }
+ // ReserveOutputBuffer ought to fail now, because the pool is depleted.
+ ASSERT_FALSE(device_->ReserveOutputBuffer());
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // Now test the interaction of client shutdown and frame delivery.
+ // Kill A1 via renderer disconnect (synchronous).
+ controller_->RemoveClient(client_a_route_1, client_a_.get());
+ // Kill B1 via session close (posts a task to disconnect).
+ EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
+ controller_->StopSession(300);
+ // Queue up another frame.
+ frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+ media::FillYUV(frame, frame_no++, 0x22, 0x44);
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ frame = device_->ReserveOutputBuffer();
+ {
+ // Kill A2 via session close (posts a task to disconnect, but A2 must not
+ // be sent either of these two frames)..
+ EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
+ controller_->StopSession(200);
+ }
+ ASSERT_TRUE(frame);
+ media::FillYUV(frame, frame_no++, 0x22, 0x44);
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ // B2 is the only client left, and is the only one that should
+ // get the frame.
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+ Mock::VerifyAndClearExpectations(client_b_.get());
+}
+
+// Exercises the OnError() codepath of VideoCaptureController, and tests the
+// behavior of various operations after the error state has been signalled.
+TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
+ media::VideoCaptureParams session_100;
+ session_100.session_id = 100;
+ session_100.width = 320;
+ session_100.height = 240;
+ session_100.frame_rate = 30;
+
+ media::VideoCaptureParams session_200 = session_100;
+ session_200.session_id = 200;
+
+ const VideoCaptureControllerID route_id(0x99);
+
+ // Start with one client.
+ controller_->AddClient(route_id, client_a_.get(),
+ base::kNullProcessHandle, session_100);
+ device_->OnError();
+ EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // Second client connects after the error state. It also should get told of
+ // the error.
+ EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
+ controller_->AddClient(route_id, client_b_.get(),
+ base::kNullProcessHandle, session_200);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_b_.get());
+
+ // OnFrameInfo from the VCD should become a no-op after the error occurs.
+ media::VideoCaptureCapability device_format(
+ 10, 10, 25, media::PIXEL_FORMAT_ARGB, 10, false,
+ media::ConstantResolutionVideoCaptureDevice);
+
+ device_->OnFrameInfo(device_format);
+ base::RunLoop().RunUntilIdle();
}
-// Try to stop session before stopping capture.
-TEST_F(VideoCaptureControllerTest, StopSession) {
- media::VideoCaptureParams capture_params;
- capture_params.session_id = vcm_->video_session_id_;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
- InSequence s;
- EXPECT_CALL(*vcm_.get(),
- StartCapture(capture_params.width,
- capture_params.height,
- controller_.get())).Times(1);
- EXPECT_CALL(*controller_handler_,
- DoFrameInfo(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferCreated(controller_handler_->controller_id_))
- .Times(AtLeast(1));
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(AtLeast(1))
- .WillOnce(StopSession(controller_.get(),
- vcm_->video_session_id_,
- message_loop_.get()));
- EXPECT_CALL(*controller_handler_,
- DoEnded(controller_handler_->controller_id_))
- .Times(1);
-
- controller_->StartCapture(controller_handler_->controller_id_,
- controller_handler_.get(),
- controller_handler_->process_handle_,
- capture_params);
- message_loop_->Run();
-
- // The session is stopped now. There should be no buffer coming from
- // controller.
- EXPECT_CALL(*controller_handler_,
- DoBufferReady(controller_handler_->controller_id_))
- .Times(0);
- message_loop_->PostDelayedTask(FROM_HERE,
- base::MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1));
- message_loop_->Run();
-
- EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
- controller_->StopCapture(controller_handler_->controller_id_,
- controller_handler_.get());
+// Exercises the OnError() codepath of VideoCaptureController, and tests the
+// behavior of various operations after the error state has been signalled.
+TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
+ media::VideoCaptureParams session_100;
+ session_100.session_id = 100;
+ session_100.width = 320;
+ session_100.height = 240;
+ session_100.frame_rate = 30;
+
+ media::VideoCaptureParams session_200 = session_100;
+ session_200.session_id = 200;
+
+ const VideoCaptureControllerID route_id(0x99);
+
+ // Start with one client.
+ controller_->AddClient(route_id, client_a_.get(),
+ base::kNullProcessHandle, session_100);
+ // OnFrameInfo from the VCD should become a no-op after the error occurs.
+ media::VideoCaptureCapability device_format(
+ 10, 10, 25, media::PIXEL_FORMAT_ARGB, 10, false,
+ media::ConstantResolutionVideoCaptureDevice);
+
+ // Start the device and get as far as exchanging buffers with the subprocess.
+ // Then, signal an error and deliver the frame. The error should be propagated
+ // to clients; the frame should not be.
+ device_->OnFrameInfo(device_format);
+ EXPECT_CALL(*client_a_, DoFrameInfo(route_id)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferCreated(route_id)).Times(kPoolSize);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ scoped_refptr<media::VideoFrame> frame = device_->ReserveOutputBuffer();
+ ASSERT_TRUE(frame);
+
+ device_->OnError();
+ device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ frame = NULL;
+
+ EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
+ base::RunLoop().RunUntilIdle();
+ Mock::VerifyAndClearExpectations(client_a_.get());
+
+ // Second client connects after the error state. It also should get told of
+ // the error.
+ EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
+ controller_->AddClient(route_id, client_b_.get(),
+ base::kNullProcessHandle, session_200);
+ Mock::VerifyAndClearExpectations(client_b_.get());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.cc b/chromium/content/browser/renderer_host/media/video_capture_host.cc
index bc7c8c19d7d..7ed77ae53d3 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
@@ -14,15 +13,6 @@
namespace content {
-struct VideoCaptureHost::Entry {
- Entry(VideoCaptureController* controller)
- : controller(controller) {}
-
- ~Entry() {}
-
- scoped_refptr<VideoCaptureController> controller;
-};
-
VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
: media_stream_manager_(media_stream_manager) {
}
@@ -32,17 +22,15 @@ VideoCaptureHost::~VideoCaptureHost() {}
void VideoCaptureHost::OnChannelClosing() {
BrowserMessageFilter::OnChannelClosing();
- // Since the IPC channel is gone, close all requested VideCaptureDevices.
+ // Since the IPC channel is gone, close all requested VideoCaptureDevices.
for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
- VideoCaptureController* controller = it->second->controller.get();
+ const base::WeakPtr<VideoCaptureController>& controller = it->second;
if (controller) {
VideoCaptureControllerID controller_id(it->first);
- controller->StopCapture(controller_id, this);
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ controller.get(), controller_id, this);
}
}
- STLDeleteValues(&entries_);
}
void VideoCaptureHost::OnDestruct() const {
@@ -95,11 +83,11 @@ void VideoCaptureHost::OnFrameInfoChanged(
const VideoCaptureControllerID& controller_id,
int width,
int height,
- int frame_per_second) {
+ int frame_rate) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoSendFrameInfoChangedOnIOThread,
- this, controller_id, width, height, frame_per_second));
+ this, controller_id, width, height, frame_rate));
}
void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
@@ -170,7 +158,7 @@ void VideoCaptureHost::DoSendFrameInfoOnIOThread(
media::VideoCaptureParams params;
params.width = format.width;
params.height = format.height;
- params.frame_per_second = format.frame_rate;
+ params.frame_rate = format.frame_rate;
params.frame_size_type = format.frame_size_type;
Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params));
Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
@@ -181,7 +169,7 @@ void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
const VideoCaptureControllerID& controller_id,
int width,
int height,
- int frame_per_second) {
+ int frame_rate) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (entries_.find(controller_id) == entries_.end())
@@ -190,7 +178,7 @@ void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
media::VideoCaptureParams params;
params.width = width;
params.height = height;
- params.frame_per_second = frame_per_second;
+ params.frame_rate = frame_rate;
Send(new VideoCaptureMsg_DeviceInfoChanged(controller_id.device_id, params));
}
@@ -215,7 +203,7 @@ void VideoCaptureHost::OnStartCapture(int device_id,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
<< ", (" << params.width << ", " << params.height << ", "
- << params.frame_per_second << ", " << params.session_id
+ << params.frame_rate << ", " << params.session_id
<< ", variable resolution device:"
<< ((params.frame_size_type ==
media::VariableResolutionVideoCaptureDevice) ? "yes" : "no")
@@ -223,45 +211,44 @@ void VideoCaptureHost::OnStartCapture(int device_id,
VideoCaptureControllerID controller_id(device_id);
DCHECK(entries_.find(controller_id) == entries_.end());
- entries_[controller_id] = new Entry(NULL);
- media_stream_manager_->video_capture_manager()->AddController(
- params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this,
- device_id, params));
+ entries_[controller_id] = base::WeakPtr<VideoCaptureController>();
+ media_stream_manager_->video_capture_manager()->StartCaptureForClient(
+ params, PeerHandle(), controller_id, this, base::Bind(
+ &VideoCaptureHost::OnControllerAdded, this, device_id, params));
}
void VideoCaptureHost::OnControllerAdded(
int device_id, const media::VideoCaptureParams& params,
- VideoCaptureController* controller) {
+ const base::WeakPtr<VideoCaptureController>& controller) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
- this, device_id, params, make_scoped_refptr(controller)));
+ this, device_id, params, controller));
}
void VideoCaptureHost::DoControllerAddedOnIOThread(
int device_id, const media::VideoCaptureParams params,
- VideoCaptureController* controller) {
+ const base::WeakPtr<VideoCaptureController>& controller) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id);
if (it == entries_.end()) {
if (controller) {
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ controller.get(), controller_id, this);
}
return;
}
- if (controller == NULL) {
+ if (!controller) {
Send(new VideoCaptureMsg_StateChanged(device_id,
VIDEO_CAPTURE_STATE_ERROR));
- delete it->second;
entries_.erase(controller_id);
return;
}
- it->second->controller = controller;
- controller->StartCapture(controller_id, this, PeerHandle(), params);
+ DCHECK(!it->second);
+ it->second = controller;
}
void VideoCaptureHost::OnStopCapture(int device_id) {
@@ -288,8 +275,8 @@ void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id);
if (it != entries_.end()) {
- scoped_refptr<VideoCaptureController> controller = it->second->controller;
- if (controller.get())
+ const base::WeakPtr<VideoCaptureController>& controller = it->second;
+ if (controller)
controller->ReturnBuffer(controller_id, this, buffer_id);
}
}
@@ -302,14 +289,11 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
if (it == entries_.end())
return;
- VideoCaptureController* controller = it->second->controller.get();
- if (controller) {
- controller->StopCapture(controller_id, this);
- media_stream_manager_->video_capture_manager()->RemoveController(
- controller, this);
+ if (it->second) {
+ media_stream_manager_->video_capture_manager()->StopCaptureForClient(
+ it->second.get(), controller_id, this);
}
- delete it->second;
- entries_.erase(controller_id);
+ entries_.erase(it);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index 025b849de94..6ce395631eb 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -39,6 +39,7 @@
#include <map>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/common/content_export.h"
@@ -46,7 +47,7 @@
#include "ipc/ipc_message.h"
namespace media {
-struct VideoCaptureCapability;
+class VideoCaptureCapability;
}
namespace content {
@@ -97,10 +98,10 @@ class CONTENT_EXPORT VideoCaptureHost
const media::VideoCaptureParams& params);
void OnControllerAdded(
int device_id, const media::VideoCaptureParams& params,
- VideoCaptureController* controller);
+ const base::WeakPtr<VideoCaptureController>& controller);
void DoControllerAddedOnIOThread(
int device_id, const media::VideoCaptureParams params,
- VideoCaptureController* controller);
+ const base::WeakPtr<VideoCaptureController>& controller);
// IPC message: Stop capture on device referenced by |device_id|.
void OnStopCapture(int device_id);
@@ -148,9 +149,12 @@ class CONTENT_EXPORT VideoCaptureHost
MediaStreamManager* media_stream_manager_;
- struct Entry;
- typedef std::map<VideoCaptureControllerID, Entry*> EntryMap;
- // A map of VideoCaptureControllerID to its state and VideoCaptureController.
+ typedef std::map<VideoCaptureControllerID,
+ base::WeakPtr<VideoCaptureController> > EntryMap;
+
+ // A map of VideoCaptureControllerID to the VideoCaptureController to which it
+ // is connected. An entry in this map holds a null controller while it is in
+ // the process of starting.
EntryMap entries_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 762148c86a2..ca1891dc426 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -20,6 +20,7 @@
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager.h"
+#include "media/base/video_frame.h"
#include "media/video/capture/video_capture_types.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -36,10 +37,10 @@ using ::testing::Return;
namespace content {
// Id used to identify the capture session between renderer and
-// video_capture_host.
-static const int kDeviceId = 1;
+// video_capture_host. This is an arbitrary value.
+static const int kDeviceId = 555;
// Id of a video capture device
-static const media::VideoCaptureSessionId kTestFakeDeviceId =
+static const media::VideoCaptureSessionId kTestFakeSessionId =
VideoCaptureManager::kStartOpenSessionId;
// Define to enable test where video is dumped to file.
@@ -57,7 +58,8 @@ class DumpVideo {
base::FilePath file_name = base::FilePath(base::StringPrintf(
FILE_PATH_LITERAL("dump_w%d_h%d.yuv"), width, height));
file_.reset(file_util::OpenFile(file_name, "wb"));
- expected_size_ = width * height * 3 / 2;
+ expected_size_ = media::VideoFrame::AllocationSize(
+ media::VideoFrame::I420, gfx::Size(width, height));
}
void NewVideoFrame(const void* buffer) {
if (file_.get() != NULL) {
@@ -146,7 +148,8 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// These handler methods do minimal things and delegate to the mock methods.
void OnNewBufferCreatedDispatch(int device_id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) {
+ uint32 length,
+ int buffer_id) {
OnNewBufferCreated(device_id, handle, length, buffer_id);
base::SharedMemory* dib = new base::SharedMemory(handle, false);
dib->Map(length);
@@ -249,14 +252,31 @@ class VideoCaptureHostTest : public testing::Test {
media::VideoCaptureParams params;
params.width = 352;
params.height = 288;
- params.frame_per_second = 30;
- params.session_id = kTestFakeDeviceId;
+ params.frame_rate = 30;
+ params.session_id = kTestFakeSessionId;
host_->OnStartCapture(kDeviceId, params);
run_loop.Run();
}
+ void StartStopCapture() {
+ // Quickly start and then stop capture, without giving much chance for
+ // asynchronous start operations to complete.
+ InSequence s;
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
+ media::VideoCaptureParams params;
+ params.width = 352;
+ params.height = 288;
+ params.frame_rate = 30;
+ params.session_id = kTestFakeSessionId;
+ host_->OnStartCapture(kDeviceId, params);
+ host_->OnStopCapture(kDeviceId);
+ run_loop.RunUntilIdle();
+ }
+
#ifdef DUMP_VIDEO
- void CaptureAndDumpVideo(int width, int heigt, int frame_rate) {
+ void CaptureAndDumpVideo(int width, int height, int frame_rate) {
InSequence s;
// 1. First - get info about the new resolution
EXPECT_CALL(*host_, OnDeviceInfo(kDeviceId));
@@ -272,9 +292,9 @@ class VideoCaptureHostTest : public testing::Test {
media::VideoCaptureParams params;
params.width = width;
- params.height = heigt;
- params.frame_per_second = frame_rate;
- params.session_id = kTestFakeDeviceId;
+ params.height = height;
+ params.frame_rate = frame_rate;
+ params.session_id = kTestFakeSessionId;
host_->SetDumpVideo(true);
host_->OnStartCapture(kDeviceId, params);
run_loop.Run();
@@ -336,6 +356,12 @@ TEST_F(VideoCaptureHostTest, StartCapture) {
StartCapture();
}
+// Disabled because of a sometimes race between completion of implicit device
+// enumeration and the capture stop. http://crbug.com/289684
+TEST_F(VideoCaptureHostTest, DISABLED_StopWhileStartOpening) {
+ StartStopCapture();
+}
+
TEST_F(VideoCaptureHostTest, StartCapturePlayStop) {
StartCapture();
NotifyPacketReady();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.cc b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
index 79da41260a3..f61aa83d093 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
@@ -33,20 +34,15 @@ namespace content {
// explicitly calling open device.
enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
-struct VideoCaptureManager::Controller {
- Controller(
- VideoCaptureController* vc_controller,
- VideoCaptureControllerEventHandler* handler)
- : controller(vc_controller),
- ready_to_delete(false) {
- handlers.push_front(handler);
- }
- ~Controller() {}
+VideoCaptureManager::DeviceEntry::DeviceEntry(
+ MediaStreamType stream_type,
+ const std::string& id,
+ scoped_ptr<VideoCaptureController> controller)
+ : stream_type(stream_type),
+ id(id),
+ video_capture_controller(controller.Pass()) {}
- scoped_refptr<VideoCaptureController> controller;
- bool ready_to_delete;
- Handlers handlers;
-};
+VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
VideoCaptureManager::VideoCaptureManager()
: listener_(NULL),
@@ -56,7 +52,6 @@ VideoCaptureManager::VideoCaptureManager()
VideoCaptureManager::~VideoCaptureManager() {
DCHECK(devices_.empty());
- DCHECK(controllers_.empty());
}
void VideoCaptureManager::Register(MediaStreamProviderListener* listener,
@@ -75,109 +70,87 @@ void VideoCaptureManager::Unregister() {
void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type;
DCHECK(listener_);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnEnumerateDevices, this, stream_type));
+ base::PostTaskAndReplyWithResult(
+ device_loop_, FROM_HERE,
+ base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, this,
+ stream_type),
+ base::Bind(&VideoCaptureManager::OnDevicesEnumerated, this, stream_type));
}
-int VideoCaptureManager::Open(const StreamDeviceInfo& device) {
+int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
- // Generate a new id for this device.
- int video_capture_session_id = new_capture_session_id_++;
+ // Generate a new id for the session being opened.
+ const int capture_session_id = new_capture_session_id_++;
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnOpen, this, video_capture_session_id,
- device));
+ DCHECK(sessions_.find(capture_session_id) == sessions_.end());
+ DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id;
- return video_capture_session_id;
+ // We just save the stream info for processing later.
+ sessions_[capture_session_id] = device_info.device;
+
+ // Notify our listener asynchronously; this ensures that we return
+ // |capture_session_id| to the caller of this function before using that same
+ // id in a listener event.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnOpened, this,
+ device_info.device.type, capture_session_id));
+ return capture_session_id;
}
void VideoCaptureManager::Close(int capture_session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClose, this, capture_session_id));
-}
-void VideoCaptureManager::Start(
- const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnStart, this, capture_params,
- video_capture_receiver));
-}
+ std::map<int, MediaStreamDevice>::iterator session_it =
+ sessions_.find(capture_session_id);
+ if (session_it == sessions_.end()) {
+ NOTREACHED();
+ return;
+ }
-void VideoCaptureManager::Stop(
- const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb) {
- DVLOG(1) << "VideoCaptureManager::Stop, id " << capture_session_id;
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnStop, this, capture_session_id,
- stopped_cb));
+ DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice(
+ session_it->second);
+ if (existing_device) {
+ // Remove any client that is still using the session. This is safe to call
+ // even if there are no clients using the session.
+ existing_device->video_capture_controller->StopSession(capture_session_id);
+
+ // StopSession() may have removed the last client, so we might need to
+ // close the device.
+ DestroyDeviceEntryIfNoClients(existing_device);
+ }
+
+ // Notify listeners asynchronously, and forget the session.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type,
+ capture_session_id));
+ sessions_.erase(session_it);
}
void VideoCaptureManager::UseFakeDevice() {
use_fake_device_ = true;
}
-void VideoCaptureManager::OnEnumerateDevices(MediaStreamType stream_type) {
- SCOPED_UMA_HISTOGRAM_TIMER(
- "Media.VideoCaptureManager.OnEnumerateDevicesTime");
- DCHECK(IsOnDeviceThread());
-
- media::VideoCaptureDevice::Names device_names;
- GetAvailableDevices(stream_type, &device_names);
-
- scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
- for (media::VideoCaptureDevice::Names::iterator it =
- device_names.begin(); it != device_names.end(); ++it) {
- bool opened = DeviceOpened(*it);
- devices->push_back(StreamDeviceInfo(
- stream_type, it->GetNameAndModel(), it->id(), opened));
- }
-
- PostOnDevicesEnumerated(stream_type, devices.Pass());
-}
-
-void VideoCaptureManager::OnOpen(int capture_session_id,
- const StreamDeviceInfo& device) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnOpenTime");
+void VideoCaptureManager::DoStartDeviceOnDeviceThread(
+ DeviceEntry* entry,
+ const media::VideoCaptureCapability& capture_params,
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> device_client) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- DCHECK(devices_.find(capture_session_id) == devices_.end());
- DVLOG(1) << "VideoCaptureManager::OnOpen, id " << capture_session_id;
-
- // Check if another session has already opened this device. If so, just
- // use that opened device.
- media::VideoCaptureDevice* opened_video_capture_device =
- GetOpenedDevice(device);
- if (opened_video_capture_device) {
- DeviceEntry& new_entry = devices_[capture_session_id];
- new_entry.stream_type = device.device.type;
- new_entry.capture_device = opened_video_capture_device;
- PostOnOpened(device.device.type, capture_session_id);
- return;
- }
scoped_ptr<media::VideoCaptureDevice> video_capture_device;
-
- // Open the device.
- switch (device.device.type) {
+ switch (entry->stream_type) {
case MEDIA_DEVICE_VIDEO_CAPTURE: {
// We look up the device id from the renderer in our local enumeration
// since the renderer does not have all the information that might be
// held in the browser-side VideoCaptureDevice::Name structure.
media::VideoCaptureDevice::Name* found =
- video_capture_devices_.FindById(device.device.id);
+ video_capture_devices_.FindById(entry->id);
if (found) {
video_capture_device.reset(use_fake_device_ ?
media::FakeVideoCaptureDevice::Create(*found) :
@@ -187,12 +160,12 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
}
case MEDIA_TAB_VIDEO_CAPTURE: {
video_capture_device.reset(
- WebContentsVideoCaptureDevice::Create(device.device.id));
+ WebContentsVideoCaptureDevice::Create(entry->id));
break;
}
case MEDIA_DESKTOP_VIDEO_CAPTURE: {
#if defined(ENABLE_SCREEN_CAPTURE)
- DesktopMediaID id = DesktopMediaID::Parse(device.device.id);
+ DesktopMediaID id = DesktopMediaID::Parse(entry->id);
if (id.type != DesktopMediaID::TYPE_NONE) {
video_capture_device = DesktopCaptureDevice::Create(id);
}
@@ -206,128 +179,123 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
}
if (!video_capture_device) {
- PostOnError(capture_session_id, kDeviceNotAvailable);
+ device_client->OnError();
return;
}
- DeviceEntry& new_entry = devices_[capture_session_id];
- new_entry.stream_type = device.device.type;
- new_entry.capture_device = video_capture_device.release();
- PostOnOpened(device.device.type, capture_session_id);
+ video_capture_device->AllocateAndStart(capture_params, device_client.Pass());
+ entry->video_capture_device = video_capture_device.Pass();
}
-void VideoCaptureManager::OnClose(int capture_session_id) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnCloseTime");
- DCHECK(IsOnDeviceThread());
- DVLOG(1) << "VideoCaptureManager::OnClose, id " << capture_session_id;
-
- VideoCaptureDevices::iterator device_it = devices_.find(capture_session_id);
- if (device_it == devices_.end()) {
+void VideoCaptureManager::StartCaptureForClient(
+ const media::VideoCaptureParams& capture_params,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, ("
+ << capture_params.width
+ << ", " << capture_params.height
+ << ", " << capture_params.frame_rate
+ << ", #" << capture_params.session_id
+ << ")";
+
+ if (capture_params.session_id == kStartOpenSessionId) {
+ // Solution for not using MediaStreamManager. Enumerate the devices and
+ // open the first one, and then start it.
+ base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE,
+ base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread,
+ this, MEDIA_DEVICE_VIDEO_CAPTURE),
+ base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this,
+ capture_params, client_render_process, client_id,
+ client_handler, done_cb));
return;
+ } else {
+ DoStartCaptureForClient(capture_params, client_render_process, client_id,
+ client_handler, done_cb);
}
- const DeviceEntry removed_entry = device_it->second;
- devices_.erase(device_it);
-
- Controllers::iterator cit = controllers_.find(removed_entry.capture_device);
- if (cit != controllers_.end()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureController::StopSession,
- cit->second->controller, capture_session_id));
- }
+}
- if (!DeviceInUse(removed_entry.capture_device)) {
- // No other users of this device, deallocate (if not done already) and
- // delete the device. No need to take care of the controller, that is done
- // by |OnStop|.
- removed_entry.capture_device->DeAllocate();
- Controllers::iterator cit = controllers_.find(removed_entry.capture_device);
- if (cit != controllers_.end()) {
- delete cit->second;
- controllers_.erase(cit);
- }
- delete removed_entry.capture_device;
+void VideoCaptureManager::DoStartCaptureForClient(
+ const media::VideoCaptureParams& capture_params,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id);
+ if (!entry) {
+ done_cb.Run(base::WeakPtr<VideoCaptureController>());
+ return;
}
- PostOnClosed(removed_entry.stream_type, capture_session_id);
-}
+ DCHECK(entry->video_capture_controller);
-void VideoCaptureManager::OnStart(
- const media::VideoCaptureParams capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnStartTime");
- DCHECK(IsOnDeviceThread());
- DCHECK(video_capture_receiver != NULL);
- DVLOG(1) << "VideoCaptureManager::OnStart, (" << capture_params.width
- << ", " << capture_params.height
- << ", " << capture_params.frame_per_second
- << ", " << capture_params.session_id
- << ")";
-
- media::VideoCaptureDevice* video_capture_device =
- GetDeviceInternal(capture_params.session_id);
- if (!video_capture_device) {
- // Invalid session id.
- video_capture_receiver->OnError();
- return;
+ // First client starts the device.
+ if (entry->video_capture_controller->GetClientCount() == 0) {
+ DVLOG(1) << "VideoCaptureManager starting device (type = "
+ << entry->stream_type << ", id = " << entry->id << ")";
+
+ media::VideoCaptureCapability params_as_capability;
+ params_as_capability.width = capture_params.width;
+ params_as_capability.height = capture_params.height;
+ params_as_capability.frame_rate = capture_params.frame_rate;
+ params_as_capability.session_id = capture_params.session_id;
+ params_as_capability.frame_size_type = capture_params.frame_size_type;
+
+ device_loop_->PostTask(FROM_HERE, base::Bind(
+ &VideoCaptureManager::DoStartDeviceOnDeviceThread, this,
+ entry, params_as_capability,
+ base::Passed(entry->video_capture_controller->NewDeviceClient())));
}
- // TODO(mcasas): Variable resolution video capture devices, are not yet
- // fully supported, see crbug.com/261410, second part, and crbug.com/266082 .
- if (capture_params.frame_size_type !=
- media::ConstantResolutionVideoCaptureDevice) {
- LOG(DFATAL) << "Only constant Video Capture resolution device supported.";
- video_capture_receiver->OnError();
+ // Run the callback first, as AddClient() may trigger OnFrameInfo().
+ done_cb.Run(entry->video_capture_controller->GetWeakPtr());
+ entry->video_capture_controller->AddClient(client_id,
+ client_handler,
+ client_render_process,
+ capture_params);
+}
+
+void VideoCaptureManager::StopCaptureForClient(
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(controller);
+ DCHECK(client_handler);
+
+ DeviceEntry* entry = GetDeviceEntryForController(controller);
+ if (!entry) {
+ NOTREACHED();
return;
}
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit != controllers_.end()) {
- cit->second->ready_to_delete = false;
- }
- // Possible errors are signaled to video_capture_receiver by
- // video_capture_device. video_capture_receiver to perform actions.
- media::VideoCaptureCapability params_as_capability_copy;
- params_as_capability_copy.width = capture_params.width;
- params_as_capability_copy.height = capture_params.height;
- params_as_capability_copy.frame_rate = capture_params.frame_per_second;
- params_as_capability_copy.session_id = capture_params.session_id;
- params_as_capability_copy.frame_size_type = capture_params.frame_size_type;
- video_capture_device->Allocate(params_as_capability_copy,
- video_capture_receiver);
- video_capture_device->Start();
-}
+ // Detach client from controller.
+ int session_id = controller->RemoveClient(client_id, client_handler);
+ DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = "
+ << session_id;
-void VideoCaptureManager::OnStop(
- const media::VideoCaptureSessionId capture_session_id,
- base::Closure stopped_cb) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.OnStopTime");
- DCHECK(IsOnDeviceThread());
- DVLOG(1) << "VideoCaptureManager::OnStop, id " << capture_session_id;
-
- VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
- if (it != devices_.end()) {
- media::VideoCaptureDevice* video_capture_device = it->second.capture_device;
- // Possible errors are signaled to video_capture_receiver by
- // video_capture_device. video_capture_receiver to perform actions.
- video_capture_device->Stop();
- video_capture_device->DeAllocate();
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit != controllers_.end()) {
- cit->second->ready_to_delete = true;
- if (cit->second->handlers.empty()) {
- delete cit->second;
- controllers_.erase(cit);
- }
- }
- }
+ // If controller has no more clients, delete controller and device.
+ DestroyDeviceEntryIfNoClients(entry);
- if (!stopped_cb.is_null())
- stopped_cb.Run();
+ // Close the session if it was auto-opened by StartCaptureForClient().
+ if (session_id == kStartOpenSessionId) {
+ sessions_.erase(session_id);
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnClosed, this,
+ MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
+ }
+}
- if (capture_session_id == kStartOpenSessionId) {
- // This device was opened from Start(), not Open(). Close it!
- OnClose(capture_session_id);
+void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
+ DCHECK(IsOnDeviceThread());
+ if (entry->video_capture_device) {
+ entry->video_capture_device->StopAndDeAllocate();
}
+ entry->video_capture_device.reset();
}
void VideoCaptureManager::OnOpened(MediaStreamType stream_type,
@@ -352,242 +320,173 @@ void VideoCaptureManager::OnClosed(MediaStreamType stream_type,
void VideoCaptureManager::OnDevicesEnumerated(
MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices) {
+ const media::VideoCaptureDevice::Names& device_names) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!listener_) {
- // Listener has been removed.
- return;
- }
- listener_->DevicesEnumerated(stream_type, *devices);
-}
-void VideoCaptureManager::OnError(MediaStreamType stream_type,
- int capture_session_id,
- MediaStreamProviderError error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!listener_) {
// Listener has been removed.
return;
}
- listener_->Error(stream_type, capture_session_id, error);
-}
-void VideoCaptureManager::PostOnOpened(
- MediaStreamType stream_type, int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnOpened, this,
- stream_type, capture_session_id));
-}
-
-void VideoCaptureManager::PostOnClosed(
- MediaStreamType stream_type, int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClosed, this,
- stream_type, capture_session_id));
-}
-
-void VideoCaptureManager::PostOnDevicesEnumerated(
- MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices) {
- DCHECK(IsOnDeviceThread());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureManager::OnDevicesEnumerated,
- this, stream_type, base::Passed(&devices)));
-}
+ // Transform from VCD::Name to StreamDeviceInfo.
+ StreamDeviceInfoArray devices;
+ for (media::VideoCaptureDevice::Names::const_iterator it =
+ device_names.begin(); it != device_names.end(); ++it) {
+ devices.push_back(StreamDeviceInfo(
+ stream_type, it->GetNameAndModel(), it->id(), false));
+ }
-void VideoCaptureManager::PostOnError(int capture_session_id,
- MediaStreamProviderError error) {
- DCHECK(IsOnDeviceThread());
- MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
- VideoCaptureDevices::const_iterator it = devices_.find(capture_session_id);
- if (it != devices_.end())
- stream_type = it->second.stream_type;
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureManager::OnError, this,
- stream_type, capture_session_id, error));
+ listener_->DevicesEnumerated(stream_type, devices);
}
bool VideoCaptureManager::IsOnDeviceThread() const {
return device_loop_->BelongsToCurrentThread();
}
-void VideoCaptureManager::GetAvailableDevices(
- MediaStreamType stream_type,
- media::VideoCaptureDevice::Names* device_names) {
+media::VideoCaptureDevice::Names
+VideoCaptureManager::GetAvailableDevicesOnDeviceThread(
+ MediaStreamType stream_type) {
+ SCOPED_UMA_HISTOGRAM_TIMER(
+ "Media.VideoCaptureManager.GetAvailableDevicesTime");
DCHECK(IsOnDeviceThread());
+ media::VideoCaptureDevice::Names result;
switch (stream_type) {
case MEDIA_DEVICE_VIDEO_CAPTURE:
// Cache the latest enumeration of video capture devices.
// We'll refer to this list again in OnOpen to avoid having to
// enumerate the devices again.
- video_capture_devices_.clear();
if (!use_fake_device_) {
- media::VideoCaptureDevice::GetDeviceNames(&video_capture_devices_);
+ media::VideoCaptureDevice::GetDeviceNames(&result);
} else {
- media::FakeVideoCaptureDevice::GetDeviceNames(&video_capture_devices_);
+ media::FakeVideoCaptureDevice::GetDeviceNames(&result);
}
- *device_names = video_capture_devices_;
+
+ // TODO(nick): The correctness of device start depends on this cache being
+ // maintained, but it seems a little odd to keep a cache here. Can we
+ // eliminate it?
+ video_capture_devices_ = result;
break;
case MEDIA_DESKTOP_VIDEO_CAPTURE:
- device_names->clear();
+ // Do nothing.
break;
default:
NOTREACHED();
break;
}
+ return result;
}
-bool VideoCaptureManager::DeviceOpened(
- const media::VideoCaptureDevice::Name& device_name) {
- DCHECK(IsOnDeviceThread());
+VideoCaptureManager::DeviceEntry*
+VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
+ const MediaStreamDevice& device_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- for (VideoCaptureDevices::iterator it = devices_.begin();
+ for (DeviceEntries::iterator it = devices_.begin();
it != devices_.end(); ++it) {
- if (device_name.id() == it->second.capture_device->device_name().id()) {
- // We've found the device!
- return true;
- }
- }
- return false;
-}
-
-media::VideoCaptureDevice* VideoCaptureManager::GetOpenedDevice(
- const StreamDeviceInfo& device_info) {
- DCHECK(IsOnDeviceThread());
-
- for (VideoCaptureDevices::iterator it = devices_.begin();
- it != devices_.end(); it++) {
- if (device_info.device.id ==
- it->second.capture_device->device_name().id()) {
- return it->second.capture_device;
+ DeviceEntry* device = *it;
+ if (device_info.type == device->stream_type &&
+ device_info.id == device->id) {
+ return device;
}
}
return NULL;
}
-bool VideoCaptureManager::DeviceInUse(
- const media::VideoCaptureDevice* video_capture_device) {
- DCHECK(IsOnDeviceThread());
-
- for (VideoCaptureDevices::iterator it = devices_.begin();
+VideoCaptureManager::DeviceEntry*
+VideoCaptureManager::GetDeviceEntryForController(
+ const VideoCaptureController* controller) {
+ // Look up |controller| in |devices_|.
+ for (DeviceEntries::iterator it = devices_.begin();
it != devices_.end(); ++it) {
- if (video_capture_device == it->second.capture_device) {
- // We've found the device!
- return true;
+ if ((*it)->video_capture_controller.get() == controller) {
+ return *it;
}
}
- return false;
+ return NULL;
}
-void VideoCaptureManager::AddController(
+void VideoCaptureManager::OpenAndStartDefaultSession(
const media::VideoCaptureParams& capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb) {
- DCHECK(handler);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread,
- this, capture_params, handler, added_cb));
-}
-
-void VideoCaptureManager::DoAddControllerOnDeviceThread(
- const media::VideoCaptureParams capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb) {
- DCHECK(IsOnDeviceThread());
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb,
+ const media::VideoCaptureDevice::Names& device_names) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- media::VideoCaptureDevice* video_capture_device =
- GetDeviceInternal(capture_params.session_id);
- scoped_refptr<VideoCaptureController> controller;
- if (video_capture_device) {
- Controllers::iterator cit = controllers_.find(video_capture_device);
- if (cit == controllers_.end()) {
- controller = new VideoCaptureController(this);
- controllers_[video_capture_device] =
- new Controller(controller.get(), handler);
- } else {
- controllers_[video_capture_device]->handlers.push_front(handler);
- controller = controllers_[video_capture_device]->controller;
- }
+ // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread().
+ // We'll mimic an Open() operation on the first element in that list.
+ DCHECK(capture_params.session_id == kStartOpenSessionId);
+ if (device_names.empty() ||
+ sessions_.count(capture_params.session_id) != 0) {
+ done_cb.Run(base::WeakPtr<VideoCaptureController>());
+ return;
}
- added_cb.Run(controller.get());
-}
-void VideoCaptureManager::RemoveController(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler) {
- DCHECK(handler);
- device_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread, this,
- make_scoped_refptr(controller), handler));
-}
+ // Open the device by creating a |sessions_| entry.
+ sessions_[capture_params.session_id] =
+ MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE,
+ device_names.front().id(),
+ device_names.front().GetNameAndModel());
-void VideoCaptureManager::DoRemoveControllerOnDeviceThread(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler) {
- DCHECK(IsOnDeviceThread());
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&VideoCaptureManager::OnOpened, this,
+ MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
- for (Controllers::iterator cit = controllers_.begin();
- cit != controllers_.end(); ++cit) {
- if (controller == cit->second->controller.get()) {
- Handlers& handlers = cit->second->handlers;
- for (Handlers::iterator hit = handlers.begin();
- hit != handlers.end(); ++hit) {
- if ((*hit) == handler) {
- handlers.erase(hit);
- break;
- }
- }
- if (handlers.empty() && cit->second->ready_to_delete) {
- delete cit->second;
- controllers_.erase(cit);
- }
- return;
- }
- }
+ DoStartCaptureForClient(capture_params, client_render_process, client_id,
+ client_handler, done_cb);
}
-media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal(
- int capture_session_id) {
- DCHECK(IsOnDeviceThread());
- VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
- if (dit != devices_.end()) {
- return dit->second.capture_device;
+void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Removal of the last client stops the device.
+ if (entry->video_capture_controller->GetClientCount() == 0) {
+ DVLOG(1) << "VideoCaptureManager stopping device (type = "
+ << entry->stream_type << ", id = " << entry->id << ")";
+
+ // The DeviceEntry is removed from |devices_| immediately. The controller is
+ // deleted immediately, and the device is freed asynchronously. After this
+ // point, subsequent requests to open this same device ID will create a new
+ // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
+ devices_.erase(entry);
+ entry->video_capture_controller.reset();
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
+ base::Owned(entry)));
}
+}
- // Solution for not using MediaStreamManager.
- // This session id won't be returned by Open().
- if (capture_session_id == kStartOpenSessionId) {
- media::VideoCaptureDevice::Names device_names;
- GetAvailableDevices(MEDIA_DEVICE_VIDEO_CAPTURE, &device_names);
- if (device_names.empty()) {
- // No devices available.
- return NULL;
- }
- StreamDeviceInfo device(MEDIA_DEVICE_VIDEO_CAPTURE,
- device_names.front().GetNameAndModel(),
- device_names.front().id(),
- false);
+VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
+ int capture_session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // Call OnOpen to open using the first device in the list.
- OnOpen(capture_session_id, device);
+ std::map<int, MediaStreamDevice>::iterator session_it =
+ sessions_.find(capture_session_id);
+ if (session_it == sessions_.end()) {
+ return NULL;
+ }
+ const MediaStreamDevice& device_info = session_it->second;
- VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
- if (dit != devices_.end()) {
- return dit->second.capture_device;
- }
+ // Check if another session has already opened this device. If so, just
+ // use that opened device.
+ DeviceEntry* const existing_device =
+ GetDeviceEntryForMediaStreamDevice(device_info);
+ if (existing_device) {
+ DCHECK_EQ(device_info.type, existing_device->stream_type);
+ return existing_device;
}
- return NULL;
+
+ scoped_ptr<VideoCaptureController> video_capture_controller(
+ new VideoCaptureController());
+ DeviceEntry* new_device = new DeviceEntry(device_info.type,
+ device_info.id,
+ video_capture_controller.Pass());
+ devices_.insert(new_device);
+ return new_device;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.h b/chromium/content/browser/renderer_host/media/video_capture_manager.h
index 34d6e626413..fc6dd92fecd 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -4,31 +4,39 @@
// VideoCaptureManager is used to open/close, start/stop, enumerate available
// video capture devices, and manage VideoCaptureController's.
-// All functions are expected to be called from Browser::IO thread.
+// All functions are expected to be called from Browser::IO thread. Some helper
+// functions (*OnDeviceThread) will dispatch operations to the device thread.
// VideoCaptureManager will open OS dependent instances of VideoCaptureDevice.
// A device can only be opened once.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
-#include <list>
#include <map>
+#include <set>
+#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process_handle.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
+#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
#include "media/video/capture/video_capture_device.h"
#include "media/video/capture/video_capture_types.h"
namespace content {
-class MockVideoCaptureManager;
class VideoCaptureController;
class VideoCaptureControllerEventHandler;
// VideoCaptureManager opens/closes and start/stops video capture devices.
class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
public:
+ // Callback used to signal the completion of a controller lookup.
+ typedef base::Callback<
+ void(const base::WeakPtr<VideoCaptureController>&)> DoneCB;
+
// Calling |Start| of this id will open the first device, even though open has
// not been called. This is used to be able to use video capture devices
// before MediaStream is implemented in Chrome and WebKit.
@@ -48,118 +56,147 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
virtual void Close(int capture_session_id) OVERRIDE;
- // Functions used to start and stop media flow.
- // Start allocates the device and no other application can use the device
- // before Stop is called. Captured video frames will be delivered to
- // video_capture_receiver.
- virtual void Start(const media::VideoCaptureParams& capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver);
-
- // Stops capture device referenced by |capture_session_id|. No more frames
- // will be delivered to the frame receiver, and |stopped_cb| will be called.
- // |stopped_cb| can be NULL.
- virtual void Stop(const media::VideoCaptureSessionId& capture_session_id,
- base::Closure stopped_cb);
-
// Used by unit test to make sure a fake device is used instead of a real
// video capture device. Due to timing requirements, the function must be
// called before EnumerateDevices and Open.
void UseFakeDevice();
- // Called by VideoCaptureHost to get a controller for |capture_params|.
- // The controller is returned via calling |added_cb|.
- void AddController(
- const media::VideoCaptureParams& capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb);
- // Called by VideoCaptureHost to remove the |controller|.
- void RemoveController(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler);
+ // Called by VideoCaptureHost to locate a capture device for |capture_params|,
+ // adding the Host as a client of the device's controller if successful. The
+ // value of |capture_params.session_id| controls which device is selected;
+ // this value should be a session id previously returned by Open().
+ //
+ // If the device is not already started (i.e., no other client is currently
+ // capturing from this device), this call will cause a VideoCaptureController
+ // and VideoCaptureDevice to be created, possibly asynchronously.
+ //
+ // On success, the controller is returned via calling |done_cb|, indicating
+ // that the client was successfully added. A NULL controller is passed to
+ // the callback on failure.
+ void StartCaptureForClient(const media::VideoCaptureParams& capture_params,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb);
+
+ // Called by VideoCaptureHost to remove |client_handler|. If this is the last
+ // client of the device, the |controller| and its VideoCaptureDevice may be
+ // destroyed. The client must not access |controller| after calling this
+ // function.
+ void StopCaptureForClient(VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler);
private:
- friend class MockVideoCaptureManager;
-
virtual ~VideoCaptureManager();
+ struct DeviceEntry;
- typedef std::list<VideoCaptureControllerEventHandler*> Handlers;
- struct Controller;
-
- // Called by the public functions, executed on device thread.
- void OnEnumerateDevices(MediaStreamType stream_type);
- void OnOpen(int capture_session_id, const StreamDeviceInfo& device);
- void OnClose(int capture_session_id);
- void OnStart(const media::VideoCaptureParams capture_params,
- media::VideoCaptureDevice::EventHandler* video_capture_receiver);
- void OnStop(const media::VideoCaptureSessionId capture_session_id,
- base::Closure stopped_cb);
- void DoAddControllerOnDeviceThread(
- const media::VideoCaptureParams capture_params,
- VideoCaptureControllerEventHandler* handler,
- base::Callback<void(VideoCaptureController*)> added_cb);
- void DoRemoveControllerOnDeviceThread(
- VideoCaptureController* controller,
- VideoCaptureControllerEventHandler* handler);
-
- // Executed on Browser::IO thread to call Listener.
+ // Helper for the kStartOpenSessionId case.
+ void OpenAndStartDefaultSession(
+ const media::VideoCaptureParams& capture_params,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb,
+ const media::VideoCaptureDevice::Names& device_names);
+
+ // Helper routine implementing StartCaptureForClient().
+ void DoStartCaptureForClient(
+ const media::VideoCaptureParams& capture_params,
+ base::ProcessHandle client_render_process,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler,
+ const DoneCB& done_cb);
+
+ // Check to see if |entry| has no clients left on its controller. If so,
+ // remove it from the list of devices, and delete it asynchronously. |entry|
+ // may be freed by this function.
+ void DestroyDeviceEntryIfNoClients(DeviceEntry* entry);
+
+ // Helpers to report an event to our Listener.
void OnOpened(MediaStreamType type, int capture_session_id);
void OnClosed(MediaStreamType type, int capture_session_id);
void OnDevicesEnumerated(MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices);
- void OnError(MediaStreamType type, int capture_session_id,
- MediaStreamProviderError error);
-
- // Executed on device thread to make sure Listener is called from
- // Browser::IO thread.
- void PostOnOpened(MediaStreamType type, int capture_session_id);
- void PostOnClosed(MediaStreamType type, int capture_session_id);
- void PostOnDevicesEnumerated(MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices);
- void PostOnError(int capture_session_id, MediaStreamProviderError error);
-
- // Helpers
- void GetAvailableDevices(MediaStreamType stream_type,
- media::VideoCaptureDevice::Names* device_names);
- bool DeviceOpened(const media::VideoCaptureDevice::Name& device_name);
- bool DeviceInUse(const media::VideoCaptureDevice* video_capture_device);
- media::VideoCaptureDevice* GetOpenedDevice(
- const StreamDeviceInfo& device_info);
+ const media::VideoCaptureDevice::Names& names);
+
+ // Find a DeviceEntry by its device ID and type, if it is already opened.
+ DeviceEntry* GetDeviceEntryForMediaStreamDevice(
+ const MediaStreamDevice& device_info);
+
+ // Find a DeviceEntry entry for the indicated session, creating a fresh one
+ // if necessary. Returns NULL if the session id is invalid.
+ DeviceEntry* GetOrCreateDeviceEntry(int capture_session_id);
+
+ // Find the DeviceEntry that owns a particular controller pointer.
+ DeviceEntry* GetDeviceEntryForController(
+ const VideoCaptureController* controller);
+
bool IsOnDeviceThread() const;
- media::VideoCaptureDevice* GetDeviceInternal(int capture_session_id);
- // The message loop of media stream device thread that this object runs on.
+ // Queries and returns the available device IDs.
+ media::VideoCaptureDevice::Names GetAvailableDevicesOnDeviceThread(
+ MediaStreamType stream_type);
+
+ // Create and Start a new VideoCaptureDevice, storing the result in
+ // |entry->video_capture_device|. Ownership of |handler| passes to
+ // the device.
+ void DoStartDeviceOnDeviceThread(
+ DeviceEntry* entry,
+ const media::VideoCaptureCapability& capture_params,
+ scoped_ptr<media::VideoCaptureDevice::EventHandler> handler);
+
+ // Stop and destroy the VideoCaptureDevice held in
+ // |entry->video_capture_device|.
+ void DoStopDeviceOnDeviceThread(DeviceEntry* entry);
+
+ // The message loop of media stream device thread, where VCD's live.
scoped_refptr<base::MessageLoopProxy> device_loop_;
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int new_capture_session_id_;
- // Only accessed from device thread.
- // VideoCaptureManager owns all VideoCaptureDevices and is responsible for
- // deleting the instances when they are not used any longer.
+ // An entry is kept in this map for every session that has been created via
+ // the Open() entry point. The keys are session_id's. This map is used to
+ // determine which device to use when StartCaptureForClient() occurs. Used
+ // only on the IO thread.
+ std::map<int, MediaStreamDevice> sessions_;
+
+ // An entry, kept in a map, that owns a VideoCaptureDevice and its associated
+ // VideoCaptureController. VideoCaptureManager owns all VideoCaptureDevices
+ // and VideoCaptureControllers and is responsible for deleting the instances
+ // when they are not used any longer.
+ //
+ // The set of currently started VideoCaptureDevice and VideoCaptureController
+ // objects is only accessed from IO thread, though the DeviceEntry instances
+ // themselves may visit to the device thread for device creation and
+ // destruction.
struct DeviceEntry {
- MediaStreamType stream_type;
- media::VideoCaptureDevice* capture_device; // Maybe shared across sessions.
+ DeviceEntry(MediaStreamType stream_type,
+ const std::string& id,
+ scoped_ptr<VideoCaptureController> controller);
+ ~DeviceEntry();
+
+ const MediaStreamType stream_type;
+ const std::string id;
+
+ // The controller. Only used from the IO thread.
+ scoped_ptr<VideoCaptureController> video_capture_controller;
+
+ // The capture device. Only used from the device thread.
+ scoped_ptr<media::VideoCaptureDevice> video_capture_device;
};
- typedef std::map<int, DeviceEntry> VideoCaptureDevices;
- VideoCaptureDevices devices_; // Maps capture_session_id to DeviceEntry.
+ typedef std::set<DeviceEntry*> DeviceEntries;
+ DeviceEntries devices_;
- // Set to true if using fake video capture devices for testing,
- // false by default. This is only used for the MEDIA_DEVICE_VIDEO_CAPTURE
- // device type.
+ // Set to true if using fake video capture devices for testing, false by
+ // default. This is only used for the MEDIA_DEVICE_VIDEO_CAPTURE device type.
bool use_fake_device_;
- // Only accessed from device thread.
- // VideoCaptureManager owns all VideoCaptureController's and is responsible
- // for deleting the instances when they are not used any longer.
- // VideoCaptureDevice is one-to-one mapped to VideoCaptureController.
- typedef std::map<media::VideoCaptureDevice*, Controller*> Controllers;
- Controllers controllers_;
-
- // We cache the enumerated video capture devices in GetAvailableDevices
- // (e.g. called by OnEnumerateDevices) and then look up the requested ID when
- // a device is opened (see OnOpen).
- // Used only on the device thread.
+ // We cache the enumerated video capture devices in
+ // GetAvailableDevicesOnDeviceThread() and then later look up the requested ID
+ // when a device is created in DoStartDeviceOnDeviceThread(). Used only on the
+ // device thread.
media::VideoCaptureDevice::Names video_capture_devices_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureManager);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 83c064655ed..34172d78cb4 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -10,8 +10,10 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
+#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "media/video/capture/video_capture_device.h"
@@ -40,30 +42,33 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
MediaStreamProviderError));
}; // class MockMediaStreamProviderListener
-// Needed as an input argument to Start().
-class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
+// Needed as an input argument to StartCaptureForClient().
+class MockFrameObserver : public VideoCaptureControllerEventHandler {
public:
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE {
- return NULL;
- }
- virtual void OnError() OVERRIDE {}
+ MOCK_METHOD1(OnError, void(const VideoCaptureControllerID& id));
+
+ virtual void OnBufferCreated(const VideoCaptureControllerID& id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id) OVERRIDE {};
+ virtual void OnBufferReady(const VideoCaptureControllerID& id,
+ int buffer_id,
+ base::Time timestamp) OVERRIDE {};
virtual void OnFrameInfo(
- const media::VideoCaptureCapability& info) OVERRIDE {}
- virtual void OnIncomingCapturedFrame(const uint8* data,
- int length,
- base::Time timestamp,
- int rotation,
- bool flip_vert,
- bool flip_horiz) OVERRIDE {}
- virtual void OnIncomingCapturedVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp) OVERRIDE {}
+ const VideoCaptureControllerID& id,
+ const media::VideoCaptureCapability& format) OVERRIDE {};
+ virtual void OnFrameInfoChanged(const VideoCaptureControllerID& id,
+ int width,
+ int height,
+ int frame_rate) OVERRIDE {};
+ virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {};
+
+ void OnGotControllerCallback(VideoCaptureControllerID) {}
};
// Test class
class VideoCaptureManagerTest : public testing::Test {
public:
- VideoCaptureManagerTest() {}
+ VideoCaptureManagerTest() : next_client_id_(1) {}
virtual ~VideoCaptureManagerTest() {}
protected:
@@ -80,6 +85,48 @@ class VideoCaptureManagerTest : public testing::Test {
virtual void TearDown() OVERRIDE {}
+ void OnGotControllerCallback(
+ VideoCaptureControllerID id,
+ base::Closure quit_closure,
+ bool expect_success,
+ const base::WeakPtr<VideoCaptureController>& controller) {
+ if (expect_success) {
+ ASSERT_TRUE(controller);
+ ASSERT_TRUE(0 == controllers_.count(id));
+ controllers_[id] = controller.get();
+ } else {
+ ASSERT_TRUE(NULL == controller);
+ }
+ quit_closure.Run();
+ }
+
+ VideoCaptureControllerID StartClient(int session_id, bool expect_success) {
+ media::VideoCaptureParams params;
+ params.session_id = session_id;
+ params.width = 320;
+ params.height = 240;
+ params.frame_rate = 30;
+
+ VideoCaptureControllerID client_id(next_client_id_++);
+ base::RunLoop run_loop;
+ vcm_->StartCaptureForClient(
+ params, base::kNullProcessHandle, client_id, frame_observer_.get(),
+ base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback,
+ base::Unretained(this), client_id, run_loop.QuitClosure(),
+ expect_success));
+ run_loop.Run();
+ return client_id;
+ }
+
+ void StopClient(VideoCaptureControllerID client_id) {
+ ASSERT_TRUE(1 == controllers_.count(client_id));
+ vcm_->StopCaptureForClient(controllers_[client_id], client_id,
+ frame_observer_.get());
+ controllers_.erase(client_id);
+ }
+
+ int next_client_id_;
+ std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
scoped_refptr<VideoCaptureManager> vcm_;
scoped_ptr<MockMediaStreamProviderListener> listener_;
scoped_ptr<base::MessageLoop> message_loop_;
@@ -108,15 +155,9 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
message_loop_->RunUntilIdle();
int video_session_id = vcm_->Open(devices.front());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
- media::VideoCaptureParams capture_params;
- capture_params.session_id = video_session_id;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
- vcm_->Start(capture_params, frame_observer_.get());
-
- vcm_->Stop(video_session_id, base::Closure());
+ StopClient(client_id);
vcm_->Close(video_session_id);
// Wait to check callbacks before removing the listener.
@@ -190,9 +231,9 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
InSequence s;
EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
.Times(1).WillOnce(SaveArg<1>(&devices));
- EXPECT_CALL(*listener_, Error(MEDIA_DEVICE_VIDEO_CAPTURE,
- _, kDeviceNotAvailable))
- .Times(1);
+ EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
+ EXPECT_CALL(*frame_observer_, OnError(_)).Times(1);
+ EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
@@ -204,11 +245,15 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
std::string device_id("id_doesnt_exist");
StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false);
- // This should fail with error code 'kDeviceNotAvailable'.
- vcm_->Open(dummy_device);
+ // This should fail with an error to the controller.
+ int session_id = vcm_->Open(dummy_device);
+ VideoCaptureControllerID client_id = StartClient(session_id, true);
+ message_loop_->RunUntilIdle();
- // Wait to check callbacks before removing the listener.
+ StopClient(client_id);
+ vcm_->Close(session_id);
message_loop_->RunUntilIdle();
+
vcm_->Unregister();
}
@@ -218,17 +263,21 @@ TEST_F(VideoCaptureManagerTest, StartUsingId) {
EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
- media::VideoCaptureParams capture_params;
- capture_params.session_id = VideoCaptureManager::kStartOpenSessionId;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
-
// Start shall trigger the Open callback.
- vcm_->Start(capture_params, frame_observer_.get());
+ VideoCaptureControllerID client_id = StartClient(
+ VideoCaptureManager::kStartOpenSessionId, true);
// Stop shall trigger the Close callback
- vcm_->Stop(VideoCaptureManager::kStartOpenSessionId, base::Closure());
+ StopClient(client_id);
+
+ // Wait to check callbacks before removing the listener.
+ message_loop_->RunUntilIdle();
+ vcm_->Unregister();
+}
+
+// Start a device without calling Open, using a non-magic ID.
+TEST_F(VideoCaptureManagerTest, StartInvalidSession) {
+ StartClient(22, false);
// Wait to check callbacks before removing the listener.
message_loop_->RunUntilIdle();
@@ -252,17 +301,12 @@ TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
int video_session_id = vcm_->Open(devices.front());
- media::VideoCaptureParams capture_params;
- capture_params.session_id = video_session_id;
- capture_params.width = 320;
- capture_params.height = 240;
- capture_params.frame_per_second = 30;
- vcm_->Start(capture_params, frame_observer_.get());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
// Close will stop the running device, an assert will be triggered in
// VideoCaptureManager destructor otherwise.
vcm_->Close(video_session_id);
- vcm_->Stop(video_session_id, base::Closure());
+ StopClient(client_id);
// Wait to check callbacks before removing the listener
message_loop_->RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index e27b703081e..91feb4d4873 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -56,8 +56,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -693,7 +693,7 @@ void RenderVideoFrame(const SkBitmap& input,
}
// The result is now ready.
- failure_handler.Release();
+ ignore_result(failure_handler.Release());
done_cb.Run(true);
}
@@ -1076,7 +1076,7 @@ void WebContentsVideoCaptureDevice::Impl::Allocate(
settings.frame_rate = frame_rate;
// Note: the value of |settings.color| doesn't matter if we use only the
// VideoFrame based methods on |consumer|.
- settings.color = media::VideoCaptureCapability::kI420;
+ settings.color = media::PIXEL_FORMAT_I420;
settings.expected_capture_delay = 0;
settings.interlaced = false;
@@ -1228,7 +1228,7 @@ WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
}
// static
-media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
+media::VideoCaptureDevice1* WebContentsVideoCaptureDevice::Create(
const std::string& device_id) {
// Parse device_id into render_process_id and render_view_id.
int render_process_id = -1;
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
index 94ac0680f6f..0dfe1d6e2f0 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
@@ -27,7 +27,7 @@ class RenderWidgetHost;
// underlying render view to be swapped out (e.g., due to navigation or
// crashes/reloads), without any interruption in capturing.
class CONTENT_EXPORT WebContentsVideoCaptureDevice
- : public media::VideoCaptureDevice {
+ : public media::VideoCaptureDevice1 {
public:
// Construct from a |device_id| string of the form:
// "virtual-media-stream://render_process_id:render_view_id", where
@@ -37,7 +37,7 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice
// WebContentsVideoCaptureDevice is itself deleted.
// TODO(miu): Passing a destroy callback suggests needing to revisit the
// design philosophy of an asynchronous DeAllocate(). http://crbug.com/158641
- static media::VideoCaptureDevice* Create(const std::string& device_id);
+ static media::VideoCaptureDevice1* Create(const std::string& device_id);
virtual ~WebContentsVideoCaptureDevice();
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index d88d553fa73..3420b09eb7b 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -310,8 +310,10 @@ class StubConsumer : public media::VideoCaptureDevice::EventHandler {
StubConsumer()
: error_encountered_(false),
wait_color_yuv_(0xcafe1950) {
- buffer_pool_ =
- new VideoCaptureBufferPool(kTestWidth * kTestHeight * 3 / 2, 2);
+ buffer_pool_ = new VideoCaptureBufferPool(
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420,
+ gfx::Size(kTestWidth, kTestHeight)),
+ 2);
EXPECT_TRUE(buffer_pool_->Allocate());
}
virtual ~StubConsumer() {}
@@ -405,7 +407,7 @@ class StubConsumer : public media::VideoCaptureDevice::EventHandler {
EXPECT_EQ(kTestWidth, info.width);
EXPECT_EQ(kTestHeight, info.height);
EXPECT_EQ(kTestFramesPerSecond, info.frame_rate);
- EXPECT_EQ(media::VideoCaptureCapability::kI420, info.color);
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, info.color);
}
private:
@@ -491,7 +493,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
// Accessors.
CaptureTestSourceController* source() { return &controller_; }
- media::VideoCaptureDevice* device() { return device_.get(); }
+ media::VideoCaptureDevice1* device() { return device_.get(); }
StubConsumer* consumer() { return &consumer_; }
void SimulateDrawEvent() {
@@ -530,7 +532,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
scoped_ptr<WebContents> web_contents_;
// Finally, the WebContentsVideoCaptureDevice under test.
- scoped_ptr<media::VideoCaptureDevice> device_;
+ scoped_ptr<media::VideoCaptureDevice1> device_;
TestBrowserThreadBundle thread_bundle_;
};
@@ -545,7 +547,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -562,7 +564,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -591,7 +593,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest,
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -617,7 +619,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -647,7 +649,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -689,7 +691,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
@@ -745,13 +747,13 @@ TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) {
1280,
720,
-2,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::Allocate,
+ base::Bind(&media::VideoCaptureDevice1::Allocate,
base::Unretained(device()),
capture_format,
consumer()));
@@ -763,7 +765,7 @@ TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
kTestWidth,
kTestHeight,
kTestFramesPerSecond,
- media::VideoCaptureCapability::kI420,
+ media::PIXEL_FORMAT_I420,
0,
false,
media::ConstantResolutionVideoCaptureDevice);
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
index 0230b26eeaa..76c536baf7c 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
@@ -36,13 +36,14 @@ bool WebRTCIdentityServiceHost::OnMessageReceived(const IPC::Message& message,
}
void WebRTCIdentityServiceHost::OnRequestIdentity(
+ int sequence_number,
const GURL& origin,
const std::string& identity_name,
const std::string& common_name) {
if (!cancel_callback_.is_null()) {
DLOG(WARNING)
<< "Request rejected because the previous request has not finished.";
- SendErrorMessage(net::ERR_INSUFFICIENT_RESOURCES);
+ SendErrorMessage(sequence_number, net::ERR_INSUFFICIENT_RESOURCES);
return;
}
@@ -50,7 +51,7 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessCookiesForOrigin(renderer_process_id_, origin)) {
DLOG(WARNING) << "Request rejected because origin access is denied.";
- SendErrorMessage(net::ERR_ACCESS_DENIED);
+ SendErrorMessage(sequence_number, net::ERR_ACCESS_DENIED);
return;
}
@@ -59,9 +60,10 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
identity_name,
common_name,
base::Bind(&WebRTCIdentityServiceHost::OnComplete,
- base::Unretained(this)));
+ base::Unretained(this),
+ sequence_number));
if (cancel_callback_.is_null()) {
- SendErrorMessage(net::ERR_UNEXPECTED);
+ SendErrorMessage(sequence_number, net::ERR_UNEXPECTED);
}
}
@@ -69,19 +71,22 @@ void WebRTCIdentityServiceHost::OnCancelRequest() {
base::ResetAndReturn(&cancel_callback_).Run();
}
-void WebRTCIdentityServiceHost::OnComplete(int status,
- const std::string& certificate,
- const std::string& private_key) {
+void WebRTCIdentityServiceHost::OnComplete(int sequence_number,
+ int status,
+ const std::string& certificate,
+ const std::string& private_key) {
cancel_callback_.Reset();
if (status == net::OK) {
- Send(new WebRTCIdentityHostMsg_IdentityReady(certificate, private_key));
+ Send(new WebRTCIdentityHostMsg_IdentityReady(
+ sequence_number, certificate, private_key));
} else {
- SendErrorMessage(status);
+ SendErrorMessage(sequence_number, status);
}
}
-void WebRTCIdentityServiceHost::SendErrorMessage(int error) {
- Send(new WebRTCIdentityHostMsg_RequestFailed(error));
+void WebRTCIdentityServiceHost::SendErrorMessage(int sequence_number,
+ int error) {
+ Send(new WebRTCIdentityHostMsg_RequestFailed(sequence_number, error));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
index 3676223fe86..3a5921c5c2d 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -37,19 +37,26 @@ class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
bool* message_was_ok) OVERRIDE;
private:
+ // |sequence_number| is the same as in the OnRequestIdentity call.
// See WebRTCIdentityStore for the meaning of the parameters.
- void OnComplete(int status,
+ void OnComplete(int sequence_number,
+ int status,
const std::string& certificate,
const std::string& private_key);
- // See WebRTCIdentityStore for the meaning of the parameters.
- void OnRequestIdentity(const GURL& origin,
+ // |sequence_number| is a renderer wide unique number for each request and
+ // will be echoed in the response to handle the possibility that the renderer
+ // cancels the request after the browser sends the response and before it's
+ // received by the renderer.
+ // See WebRTCIdentityStore for the meaning of the other parameters.
+ void OnRequestIdentity(int sequence_number,
+ const GURL& origin,
const std::string& identity_name,
const std::string& common_name);
void OnCancelRequest();
- void SendErrorMessage(int error);
+ void SendErrorMessage(int sequence_number, int error);
int renderer_process_id_;
base::Closure cancel_callback_;
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
index 341378d3c7b..cbedf512bc5 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
@@ -24,6 +24,7 @@ static const char FAKE_CERTIFICATE[] = "fake cert";
static const char FAKE_PRIVATE_KEY[] = "fake private key";
static const int FAKE_ERROR = 100;
static const int FAKE_RENDERER_ID = 10;
+const int FAKE_SEQUENCE_NUMBER = 1;
class MockWebRTCIdentityStore : public WebRTCIdentityStore {
public:
@@ -105,8 +106,10 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
void SendRequestToHost() {
bool ok;
host_->OnMessageReceived(
- WebRTCIdentityMsg_RequestIdentity(
- GURL(FAKE_ORIGIN), FAKE_IDENTITY_NAME, FAKE_COMMON_NAME),
+ WebRTCIdentityMsg_RequestIdentity(FAKE_SEQUENCE_NUMBER,
+ GURL(FAKE_ORIGIN),
+ FAKE_IDENTITY_NAME,
+ FAKE_COMMON_NAME),
&ok);
ASSERT_TRUE(ok);
}
@@ -122,9 +125,10 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_RequestFailed::ID);
- Tuple1<int> error_in_message;
+ Tuple2<int, int> error_in_message;
WebRTCIdentityHostMsg_RequestFailed::Read(&ipc, &error_in_message);
- EXPECT_EQ(error, error_in_message.a);
+ EXPECT_EQ(FAKE_SEQUENCE_NUMBER, error_in_message.a);
+ EXPECT_EQ(error, error_in_message.b);
}
void VerifyIdentityReadyMessage(const std::string& cert,
@@ -133,10 +137,11 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_IdentityReady::ID);
- Tuple2<std::string, std::string> identity_in_message;
+ Tuple3<int, std::string, std::string> identity_in_message;
WebRTCIdentityHostMsg_IdentityReady::Read(&ipc, &identity_in_message);
- EXPECT_EQ(cert, identity_in_message.a);
- EXPECT_EQ(key, identity_in_message.b);
+ EXPECT_EQ(FAKE_SEQUENCE_NUMBER, identity_in_message.a);
+ EXPECT_EQ(cert, identity_in_message.b);
+ EXPECT_EQ(key, identity_in_message.c);
}
protected:
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
index 3cb2af1397b..646b358ac8d 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
@@ -4,7 +4,7 @@
#include "content/public/browser/native_web_keyboard_event.h"
-#include "ui/base/events/event_constants.h"
+#include "ui/events/event_constants.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
index 1658d8d3dc2..ad3aae357cb 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "content/browser/renderer_host/web_input_event_aura.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
namespace {
@@ -77,7 +77,8 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
nativeKeyCode = character;
text[0] = character;
unmodifiedText[0] = character;
- isSystemKey = (state & ui::EF_ALT_DOWN) != 0;
+ isSystemKey =
+ (state & ui::EF_ALT_DOWN) != 0 && (state & ui::EF_ALTGR_DOWN) == 0;
setKeyIdentifierFromWindowsKeyCode();
}
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
index f7631945fec..74ce6a36cbb 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_gtk.cc
@@ -6,9 +6,7 @@
#include <gdk/gdk.h>
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
-
-using WebKit::WebInputEventFactory;
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
namespace {
@@ -32,7 +30,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent()
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
- : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(&native_event->key)),
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(&native_event->key)),
skip_in_browser(false),
match_edit_command(false) {
CopyEventTo(native_event, &os_event);
@@ -41,9 +39,9 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
NativeWebKeyboardEvent::NativeWebKeyboardEvent(wchar_t character,
int state,
double time_stamp_seconds)
- : WebKeyboardEvent(WebInputEventFactory::keyboardEvent(character,
- state,
- time_stamp_seconds)),
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(character,
+ state,
+ time_stamp_seconds)),
os_event(NULL),
skip_in_browser(false),
match_edit_command(false) {
diff --git a/chromium/content/browser/renderer_host/overscroll_configuration.cc b/chromium/content/browser/renderer_host/overscroll_configuration.cc
index 77585e5fb02..f7c5579f56f 100644
--- a/chromium/content/browser/renderer_host/overscroll_configuration.cc
+++ b/chromium/content/browser/renderer_host/overscroll_configuration.cc
@@ -11,7 +11,8 @@ namespace {
float g_horiz_threshold_complete = 0.25f;
float g_vert_threshold_complete = 0.20f;
-float g_horiz_threshold_start = 50.f;
+float g_horiz_threshold_start_touchscreen = 50.f;
+float g_horiz_threshold_start_touchpad = 50.f;
float g_vert_threshold_start = 0.f;
float g_horiz_resist_after = 30.f;
@@ -31,8 +32,12 @@ void SetOverscrollConfig(OverscrollConfig config, float value) {
g_vert_threshold_complete = value;
break;
- case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START:
- g_horiz_threshold_start = value;
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN:
+ g_horiz_threshold_start_touchscreen = value;
+ break;
+
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD:
+ g_horiz_threshold_start_touchpad = value;
break;
case OVERSCROLL_CONFIG_VERT_THRESHOLD_START:
@@ -61,8 +66,11 @@ float GetOverscrollConfig(OverscrollConfig config) {
case OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE:
return g_vert_threshold_complete;
- case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START:
- return g_horiz_threshold_start;
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN:
+ return g_horiz_threshold_start_touchscreen;
+
+ case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD:
+ return g_horiz_threshold_start_touchpad;
case OVERSCROLL_CONFIG_VERT_THRESHOLD_START:
return g_vert_threshold_start;
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 3fed4c332a7..f07efab61f4 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -9,6 +9,8 @@
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/browser/render_widget_host_view.h"
+using WebKit::WebInputEvent;
+
namespace content {
OverscrollController::OverscrollController(
@@ -62,23 +64,25 @@ bool OverscrollController::WillDispatchEvent(
// touch-scrolls maintain state in the renderer side (in the compositor, for
// example), and the event that completes this action needs to be sent to
// the renderer so that those states can be updated/reset appropriately.
- // Send the event through the host when appropriate.
- if (ShouldForwardToHost(event)) {
+ if (WebKit::WebInputEvent::isGestureEventType(event.type)) {
+ // A gesture-event isn't sent to the GestureEventFilter when overscroll is
+ // in progress. So dispatch the event through the RenderWidgetHost so that
+ // it can reach the GestureEventFilter.
const WebKit::WebGestureEvent& gevent =
static_cast<const WebKit::WebGestureEvent&>(event);
return render_widget_host_->ShouldForwardGestureEvent(
GestureEventWithLatencyInfo(gevent, latency_info));
}
- return false;
+ return true;
}
if (overscroll_mode_ != OVERSCROLL_NONE && DispatchEventResetsState(event)) {
SetOverscrollMode(OVERSCROLL_NONE);
- // The overscroll gesture status is being reset. If the event is a
- // gesture event (from either touchscreen or trackpad), then make sure the
- // host gets the event first (if it didn't already process it).
- if (ShouldForwardToHost(event)) {
+ if (WebKit::WebInputEvent::isGestureEventType(event.type)) {
+ // A gesture-event isn't sent to the GestureEventFilter when overscroll is
+ // in progress. So dispatch the event through the RenderWidgetHost so that
+ // it can reach the GestureEventFilter.
const WebKit::WebGestureEvent& gevent =
static_cast<const WebKit::WebGestureEvent&>(event);
return render_widget_host_->ShouldForwardGestureEvent(
@@ -90,16 +94,9 @@ bool OverscrollController::WillDispatchEvent(
}
if (overscroll_mode_ != OVERSCROLL_NONE) {
- // Consume the event and update overscroll state when in the middle of the
- // overscroll gesture.
- ProcessEventForOverscroll(event);
-
- if (event.type == WebKit::WebInputEvent::TouchEnd ||
- event.type == WebKit::WebInputEvent::TouchCancel ||
- event.type == WebKit::WebInputEvent::TouchMove) {
- return true;
- }
- return false;
+ // Consume the event only if it updates the overscroll state.
+ if (ProcessEventForOverscroll(event))
+ return false;
}
return true;
@@ -224,24 +221,29 @@ bool OverscrollController::DispatchEventResetsState(
}
}
-void OverscrollController::ProcessEventForOverscroll(
+bool OverscrollController::ProcessEventForOverscroll(
const WebKit::WebInputEvent& event) {
+ bool event_processed = false;
switch (event.type) {
case WebKit::WebInputEvent::MouseWheel: {
const WebKit::WebMouseWheelEvent& wheel =
static_cast<const WebKit::WebMouseWheelEvent&>(event);
if (!wheel.hasPreciseScrollingDeltas)
- return;
+ break;
ProcessOverscroll(wheel.deltaX * wheel.accelerationRatioX,
- wheel.deltaY * wheel.accelerationRatioY);
+ wheel.deltaY * wheel.accelerationRatioY,
+ wheel.type);
+ event_processed = true;
break;
}
case WebKit::WebInputEvent::GestureScrollUpdate: {
const WebKit::WebGestureEvent& gesture =
static_cast<const WebKit::WebGestureEvent&>(event);
ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
- gesture.data.scrollUpdate.deltaY);
+ gesture.data.scrollUpdate.deltaY,
+ gesture.type);
+ event_processed = true;
break;
}
case WebKit::WebInputEvent::GestureFlingStart: {
@@ -254,12 +256,14 @@ void OverscrollController::ProcessEventForOverscroll(
if ((overscroll_mode_ == OVERSCROLL_WEST && velocity_x < 0) ||
(overscroll_mode_ == OVERSCROLL_EAST && velocity_x > 0)) {
CompleteAction();
+ event_processed = true;
break;
}
} else if (fabs(velocity_y) > kFlingVelocityThreshold) {
if ((overscroll_mode_ == OVERSCROLL_NORTH && velocity_y < 0) ||
(overscroll_mode_ == OVERSCROLL_SOUTH && velocity_y > 0)) {
CompleteAction();
+ event_processed = true;
break;
}
}
@@ -274,15 +278,20 @@ void OverscrollController::ProcessEventForOverscroll(
WebKit::WebInputEvent::isTouchEventType(event.type))
<< "Received unexpected event: " << event.type;
}
+ return event_processed;
}
-void OverscrollController::ProcessOverscroll(float delta_x, float delta_y) {
+void OverscrollController::ProcessOverscroll(float delta_x,
+ float delta_y,
+ WebKit::WebInputEvent::Type type) {
if (scroll_state_ != STATE_CONTENT_SCROLLING)
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
float horiz_threshold = GetOverscrollConfig(
- OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START);
+ WebInputEvent::isGestureEventType(type) ?
+ OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN :
+ OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD);
float vert_threshold = GetOverscrollConfig(
OVERSCROLL_CONFIG_VERT_THRESHOLD_START);
if (fabs(overscroll_delta_x_) <= horiz_threshold &&
@@ -359,14 +368,4 @@ void OverscrollController::SetOverscrollMode(OverscrollMode mode) {
delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_);
}
-bool OverscrollController::ShouldForwardToHost(
- const WebKit::WebInputEvent& event) const {
- if (!WebKit::WebInputEvent::isGestureEventType(event.type))
- return false;
-
- // If the RenderWidgetHost already processed this event, then the event must
- // not be sent again.
- return !render_widget_host_->HasQueuedGestureEvents();
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index fc1fc5eb47f..fab531947ee 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -89,13 +89,16 @@ class OverscrollController {
// overscroll gesture status.
bool DispatchEventResetsState(const WebKit::WebInputEvent& event) const;
- // Processes an event and updates internal state for overscroll.
- void ProcessEventForOverscroll(const WebKit::WebInputEvent& event);
+ // Processes an event to update the internal state for overscroll. Returns
+ // true if the state is updated, false otherwise.
+ bool ProcessEventForOverscroll(const WebKit::WebInputEvent& event);
// Processes horizontal overscroll. This can update both the overscroll mode
// and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
// and |overscroll_delta_y_|).
- void ProcessOverscroll(float delta_x, float delta_y);
+ void ProcessOverscroll(float delta_x,
+ float delta_y,
+ WebKit::WebInputEvent::Type event_type);
// Completes the desired action from the current gesture.
void CompleteAction();
@@ -104,10 +107,6 @@ class OverscrollController {
// appropriate).
void SetOverscrollMode(OverscrollMode new_mode);
- // Returns whether the input event should be forwarded to the
- // RenderWidgetHost.
- bool ShouldForwardToHost(const WebKit::WebInputEvent& event) const;
-
// The RenderWidgetHost that owns this overscroll controller.
RenderWidgetHostImpl* render_widget_host_;
diff --git a/chromium/content/browser/renderer_host/p2p/OWNERS b/chromium/content/browser/renderer_host/p2p/OWNERS
index 17c3a1e6983..f12c2d60e83 100644
--- a/chromium/content/browser/renderer_host/p2p/OWNERS
+++ b/chromium/content/browser/renderer_host/p2p/OWNERS
@@ -1,2 +1,3 @@
-sergeyu@chromium.org
hclam@chromium.org
+mallinath@chromium.org
+sergeyu@chromium.org
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index f1249d51e89..d1a60b451a8 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -51,7 +51,9 @@ class P2PSocketDispatcherHost::DnsRequest {
net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
int result = resolver_.Resolve(
- info, &addresses_,
+ info,
+ net::DEFAULT_PRIORITY,
+ &addresses_,
base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone,
base::Unretained(this)),
net::BoundNetLog());
@@ -190,8 +192,8 @@ void P2PSocketDispatcherHost::OnCreateSocket(
return;
}
- scoped_ptr<P2PSocketHost> socket(
- P2PSocketHost::Create(this, socket_id, type, url_context_.get()));
+ scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create(
+ this, socket_id, type, url_context_.get(), &throttler_));
if (!socket) {
Send(new P2PMsg_OnError(socket_id));
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
index 8a31ae558b1..2369eb2dbea 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -7,6 +7,7 @@
#include <map>
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "content/common/p2p_sockets.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
@@ -84,6 +85,7 @@ class P2PSocketDispatcherHost
bool monitoring_networks_;
std::set<DnsRequest*> dns_requests_;
+ P2PMessageThrottler throttler_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
index 027bf2a608b..4b45e99adad 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.cc
@@ -15,7 +15,8 @@ const uint32 kStunMagicCookie = 0x2112A442;
namespace content {
-P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender, int id)
+P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender,
+ int id)
: message_sender_(message_sender),
id_(id),
state_(STATE_UNINITIALIZED) {
@@ -73,11 +74,11 @@ bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) {
// static
P2PSocketHost* P2PSocketHost::Create(
IPC::Sender* message_sender, int id, P2PSocketType type,
- net::URLRequestContextGetter* url_context) {
+ net::URLRequestContextGetter* url_context,
+ P2PMessageThrottler* throttler) {
switch (type) {
case P2P_SOCKET_UDP:
- return new P2PSocketHostUdp(message_sender, id);
-
+ return new P2PSocketHostUdp(message_sender, id, throttler);
case P2P_SOCKET_TCP_SERVER:
return new P2PSocketHostTcpServer(
message_sender, id, P2P_SOCKET_TCP_CLIENT);
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index 8228300408e..fa186c84b49 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -7,7 +7,6 @@
#include "content/common/content_export.h"
#include "content/common/p2p_sockets.h"
-
#include "net/base/ip_endpoint.h"
namespace IPC {
@@ -19,6 +18,7 @@ class URLRequestContextGetter;
}
namespace content {
+class P2PMessageThrottler;
// Base class for P2P sockets.
class CONTENT_EXPORT P2PSocketHost {
@@ -27,7 +27,8 @@ class CONTENT_EXPORT P2PSocketHost {
// Creates P2PSocketHost of the specific type.
static P2PSocketHost* Create(IPC::Sender* message_sender,
int id, P2PSocketType type,
- net::URLRequestContextGetter* url_context);
+ net::URLRequestContextGetter* url_context,
+ P2PMessageThrottler* throttler);
virtual ~P2PSocketHost();
@@ -45,6 +46,8 @@ class CONTENT_EXPORT P2PSocketHost {
protected:
friend class P2PSocketHostTcpTestBase;
+ // TODO(mallinath) - Remove this below enum and use one defined in
+ // libjingle/souce/talk/p2p/base/stun.h
enum StunMessageType {
STUN_BINDING_REQUEST = 0x0001,
STUN_BINDING_RESPONSE = 0x0101,
@@ -58,7 +61,15 @@ class CONTENT_EXPORT P2PSocketHost {
STUN_SEND_REQUEST = 0x0004,
STUN_SEND_RESPONSE = 0x0104,
STUN_SEND_ERROR_RESPONSE = 0x0114,
- STUN_DATA_INDICATION = 0x0115
+ STUN_DATA_INDICATION = 0x0115,
+ TURN_SEND_INDICATION = 0x0016,
+ TURN_DATA_INDICATION = 0x0017,
+ TURN_CREATE_PERMISSION_REQUEST = 0x0008,
+ TURN_CREATE_PERMISSION_RESPONSE = 0x0108,
+ TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118,
+ TURN_CHANNEL_BIND_REQUEST = 0x0009,
+ TURN_CHANNEL_BIND_RESPONSE = 0x0109,
+ TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119,
};
enum State {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 8e13bf8f5b5..de9927a7168 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -134,18 +134,23 @@ void P2PSocketHostTcpBase::OnConnected(int result) {
if (IsTlsClientSocket(type_)) {
state_ = STATE_TLS_CONNECTING;
StartTls();
- } else {
- if (IsPseudoTlsClientSocket(type_)) {
- socket_.reset(new jingle_glue::FakeSSLClientSocket(socket_.release()));
+ } else if (IsPseudoTlsClientSocket(type_)) {
+ scoped_ptr<net::StreamSocket> transport_socket = socket_.Pass();
+ socket_.reset(
+ new jingle_glue::FakeSSLClientSocket(transport_socket.Pass()));
+ state_ = STATE_TLS_CONNECTING;
+ int status = socket_->Connect(
+ base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
+ base::Unretained(this)));
+ if (status != net::ERR_IO_PENDING) {
+ ProcessTlsSslConnectDone(status);
}
-
+ } else {
// If we are not doing TLS, we are ready to send data now.
// In case of TLS, SignalConnect will be sent only after TLS handshake is
// successfull. So no buffering will be done at socket handlers if any
// packets sent before that by the application.
- state_ = STATE_OPEN;
- DoSendSocketCreateMsg();
- DoRead();
+ OnOpen();
}
}
@@ -155,7 +160,7 @@ void P2PSocketHostTcpBase::StartTls() {
scoped_ptr<net::ClientSocketHandle> socket_handle(
new net::ClientSocketHandle());
- socket_handle->set_socket(socket_.release());
+ socket_handle->SetSocket(socket_.Pass());
net::SSLClientSocketContext context;
context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier();
@@ -171,24 +176,27 @@ void P2PSocketHostTcpBase::StartTls() {
net::ClientSocketFactory::GetDefaultFactory();
DCHECK(socket_factory);
- socket_.reset(socket_factory->CreateSSLClientSocket(
- socket_handle.release(), dest_host_port_pair, ssl_config, context));
+ socket_ = socket_factory->CreateSSLClientSocket(
+ socket_handle.Pass(), dest_host_port_pair, ssl_config, context);
int status = socket_->Connect(
- base::Bind(&P2PSocketHostTcpBase::ProcessTlsConnectDone,
+ base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
base::Unretained(this)));
if (status != net::ERR_IO_PENDING) {
- ProcessTlsConnectDone(status);
+ ProcessTlsSslConnectDone(status);
}
}
-void P2PSocketHostTcpBase::ProcessTlsConnectDone(int status) {
+void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) {
DCHECK_NE(status, net::ERR_IO_PENDING);
DCHECK_EQ(state_, STATE_TLS_CONNECTING);
if (status != net::OK) {
OnError();
return;
}
+ OnOpen();
+}
+void P2PSocketHostTcpBase::OnOpen() {
state_ = STATE_OPEN;
DoSendSocketCreateMsg();
DoRead();
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
index e5fa08ff93f..c0047a1c26a 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -61,7 +61,7 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
// SSL/TLS connection functions.
void StartTls();
- void ProcessTlsConnectDone(int status);
+ void ProcessTlsSslConnectDone(int status);
void DidCompleteRead(int result);
void DoRead();
@@ -74,6 +74,8 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
void OnRead(int result);
void OnWritten(int result);
+ // Helper method to send socket create message and start read.
+ void OnOpen();
void DoSendSocketCreateMsg();
net::IPEndPoint remote_address_;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
new file mode 100644
index 00000000000..50a4dd0ac83
--- /dev/null
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
+#include "third_party/libjingle/source/talk/base/ratelimiter.h"
+#include "third_party/libjingle/source/talk/base/timing.h"
+
+namespace content {
+
+namespace {
+
+const int kMaxIceMessageBandwidth = 256 * 1024;
+
+} // namespace
+
+
+P2PMessageThrottler::P2PMessageThrottler()
+ : timing_(new talk_base::Timing()),
+ rate_limiter_(new talk_base::RateLimiter(kMaxIceMessageBandwidth, 1.0)) {
+}
+
+P2PMessageThrottler::~P2PMessageThrottler() {
+}
+
+void P2PMessageThrottler::SetTiming(scoped_ptr<talk_base::Timing> timing) {
+ timing_ = timing.Pass();
+}
+
+void P2PMessageThrottler::SetSendIceBandwidth(int bandwidth_kbps) {
+ rate_limiter_.reset(new talk_base::RateLimiter(bandwidth_kbps, 1.0));
+}
+
+bool P2PMessageThrottler::DropNextPacket(size_t packet_len) {
+ double now = timing_->TimerNow();
+ if (!rate_limiter_->CanUse(packet_len, now)) {
+ // Exceeding the send rate, this packet should be dropped.
+ return true;
+ }
+
+ rate_limiter_->Use(packet_len, now);
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
new file mode 100644
index 00000000000..166d30054f5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace talk_base {
+class RateLimiter;
+class Timing;
+}
+
+namespace content {
+
+// A very simple message throtller. User of this class must drop the packet if
+// DropNextPacket returns false for that packet. This method verifies the
+// current sendrate against the required sendrate.
+
+class CONTENT_EXPORT P2PMessageThrottler {
+ public:
+ P2PMessageThrottler();
+ virtual ~P2PMessageThrottler();
+
+ void SetTiming(scoped_ptr<talk_base::Timing> timing);
+ bool DropNextPacket(size_t packet_len);
+ void SetSendIceBandwidth(int bandwith_kbps);
+
+ private:
+ scoped_ptr<talk_base::Timing> timing_;
+ scoped_ptr<talk_base::RateLimiter> rate_limiter_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PMessageThrottler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_THROTTLER_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
index bcfb282a2c4..54c2b4cd4ed 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "content/common/p2p_messages.h"
#include "ipc/ipc_sender.h"
#include "net/base/io_buffer.h"
@@ -61,11 +62,14 @@ P2PSocketHostUdp::PendingPacket::PendingPacket(
P2PSocketHostUdp::PendingPacket::~PendingPacket() {
}
-P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender, int id)
+P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
+ int id,
+ P2PMessageThrottler* throttler)
: P2PSocketHost(message_sender, id),
socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())),
send_pending_(false),
- send_packet_count_(0) {
+ send_packet_count_(0),
+ throttler_(throttler) {
}
P2PSocketHostUdp::~P2PSocketHostUdp() {
@@ -180,6 +184,12 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
OnError();
return;
}
+
+ if (throttler_->DropNextPacket(data.size())) {
+ LOG(INFO) << "STUN message is dropped due to high volume.";
+ // Do not reset socket.
+ return;
+ }
}
if (send_pending_) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
index e9eb36393f4..befac2cae12 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -21,9 +21,12 @@
namespace content {
+class P2PMessageThrottler;
+
class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
public:
- P2PSocketHostUdp(IPC::Sender* message_sender, int id);
+ P2PSocketHostUdp(IPC::Sender* message_sender, int id,
+ P2PMessageThrottler* throttler);
virtual ~P2PSocketHostUdp();
// P2PSocketHost overrides.
@@ -71,6 +74,7 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
// Set of peer for which we have received STUN binding request or
// response or relay allocation request or response.
ConnectedPeerSet connected_peers_;
+ P2PMessageThrottler* throttler_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketHostUdp);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
index 9ecd56abd54..d42efbe3c35 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
@@ -10,12 +10,14 @@
#include "base/logging.h"
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
+#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/udp/datagram_server_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/base/timing.h"
using ::testing::_;
using ::testing::DeleteArg;
@@ -24,6 +26,16 @@ using ::testing::Return;
namespace {
+class FakeTiming : public talk_base::Timing {
+ public:
+ FakeTiming() : now_(0.0) {}
+ virtual double TimerNow() OVERRIDE { return now_; }
+ void set_now(double now) { now_ = now; }
+
+ private:
+ double now_;
+};
+
class FakeDatagramServerSocket : public net::DatagramServerSocket {
public:
typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket;
@@ -161,7 +173,7 @@ class P2PSocketHostUdpTest : public testing::Test {
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_.reset(new P2PSocketHostUdp(&sender_, 0));
+ socket_host_.reset(new P2PSocketHostUdp(&sender_, 0, &throttler_));
socket_ = new FakeDatagramServerSocket(&sent_packets_);
socket_host_->socket_.reset(socket_);
@@ -170,8 +182,12 @@ class P2PSocketHostUdpTest : public testing::Test {
dest1_ = ParseAddress(kTestIpAddress1, kTestPort1);
dest2_ = ParseAddress(kTestIpAddress2, kTestPort2);
+
+ scoped_ptr<talk_base::Timing> timing(new FakeTiming());
+ throttler_.SetTiming(timing.Pass());
}
+ P2PMessageThrottler throttler_;
std::deque<FakeDatagramServerSocket::UDPPacket> sent_packets_;
FakeDatagramServerSocket* socket_; // Owned by |socket_host_|.
scoped_ptr<P2PSocketHostUdp> socket_host_;
@@ -289,4 +305,62 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
socket_host_->Send(dest2_, packet);
}
+// Verify throttler not allowing unlimited sending of ICE messages to
+// any destination.
+TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimit) {
+ EXPECT_CALL(sender_, Send(
+ MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+ .Times(2)
+ .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
+ std::vector<char> packet1;
+ CreateStunRequest(&packet1);
+ throttler_.SetSendIceBandwidth(packet1.size() * 2);
+ socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest2_, packet1);
+
+ net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2222);
+ // This packet must be dropped by the throttler.
+ socket_host_->Send(dest3, packet1);
+ ASSERT_EQ(sent_packets_.size(), 2U);
+}
+
+// Verify we can send packets to a known destination when ICE throttling is
+// active.
+TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimitAfterReceive) {
+ // Receive packet from |dest1_|.
+ std::vector<char> request_packet;
+ CreateStunRequest(&request_packet);
+
+ EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
+ .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+ socket_->ReceivePacket(dest1_, request_packet);
+
+ EXPECT_CALL(sender_, Send(
+ MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+ .Times(4)
+ .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
+ std::vector<char> packet1;
+ CreateStunRequest(&packet1);
+ throttler_.SetSendIceBandwidth(packet1.size());
+ // |dest1_| is known address, throttling will not be applied.
+ socket_host_->Send(dest1_, packet1);
+ // Trying to send the packet to dest1_ in the same window. It should go.
+ socket_host_->Send(dest1_, packet1);
+
+ // Throttler should allow this packet to go through.
+ socket_host_->Send(dest2_, packet1);
+
+ net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2223);
+ // This packet will be dropped, as limit only for a single packet.
+ socket_host_->Send(dest3, packet1);
+ net::IPEndPoint dest4 = ParseAddress(kTestIpAddress1, 2224);
+ // This packet should also be dropped.
+ socket_host_->Send(dest4, packet1);
+ // |dest1| is known, we can send as many packets to it.
+ socket_host_->Send(dest1_, packet1);
+ ASSERT_EQ(sent_packets_.size(), 4U);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/OWNERS b/chromium/content/browser/renderer_host/pepper/OWNERS
index dc19a03cb21..33d4c55751a 100644
--- a/chromium/content/browser/renderer_host/pepper/OWNERS
+++ b/chromium/content/browser/renderer_host/pepper/OWNERS
@@ -1,3 +1,4 @@
+bbudge@chromium.org
dmichael@chromium.org
raymes@chromium.org
yzshen@chromium.org
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index 10eef8b5515..db3f8eff2ae 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/render_view_host.h"
@@ -18,23 +19,17 @@ BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
ppapi::PpapiPermissions permissions,
base::ProcessHandle plugin_child_process,
IPC::ChannelProxy* channel,
- net::HostResolver* host_resolver,
int render_process_id,
int render_view_id,
const base::FilePath& profile_directory) {
- scoped_refptr<PepperMessageFilter> pepper_message_filter(
- new PepperMessageFilter(permissions,
- host_resolver,
- render_process_id,
- render_view_id));
-
// The plugin name and path shouldn't be needed for external plugins.
BrowserPpapiHostImpl* browser_ppapi_host =
new BrowserPpapiHostImpl(sender, permissions, std::string(),
- base::FilePath(), profile_directory, true,
- pepper_message_filter);
+ base::FilePath(), profile_directory, true);
browser_ppapi_host->set_plugin_process_handle(plugin_child_process);
+ scoped_refptr<PepperMessageFilter> pepper_message_filter(
+ new PepperMessageFilter());
channel->AddFilter(pepper_message_filter);
channel->AddFilter(browser_ppapi_host->message_filter().get());
channel->AddFilter(new TraceMessageFilter());
@@ -48,17 +43,17 @@ BrowserPpapiHostImpl::BrowserPpapiHostImpl(
const std::string& plugin_name,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
- bool external_plugin,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
+ bool external_plugin)
: ppapi_host_(new ppapi::host::PpapiHost(sender, permissions)),
plugin_process_handle_(base::kNullProcessHandle),
plugin_name_(plugin_name),
plugin_path_(plugin_path),
profile_data_directory_(profile_data_directory),
- external_plugin_(external_plugin) {
+ external_plugin_(external_plugin),
+ ssl_context_helper_(new SSLContextHelper()) {
message_filter_ = new HostMessageFilter(ppapi_host_.get());
ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
- new ContentBrowserPepperHostFactory(this, pepper_message_filter)));
+ new ContentBrowserPepperHostFactory(this)));
}
BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index c46ab13b220..f16d1d82c18 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -13,7 +13,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
+#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/browser_ppapi_host.h"
@@ -36,10 +36,7 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
const std::string& plugin_name,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
- bool external_plugin,
- // TODO (ygorshenin@): remove this once TCP sockets are
- // converted to the new design.
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ bool external_plugin);
virtual ~BrowserPpapiHostImpl();
// BrowserPpapiHost.
@@ -72,6 +69,10 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
return message_filter_;
}
+ const scoped_refptr<SSLContextHelper>& ssl_context_helper() const {
+ return ssl_context_helper_;
+ }
+
private:
friend class BrowserPpapiHostTest;
@@ -103,6 +104,8 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
// BrowserPpapiHost::CreateExternalPluginProcess.
bool external_plugin_;
+ scoped_refptr<SSLContextHelper> ssl_context_helper_;
+
// Tracks all PP_Instances in this plugin and associated renderer-related
// data.
typedef std::map<PP_Instance, PepperRendererInstanceData> InstanceMap;
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
index a8c257abacd..c338a990f59 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
@@ -16,8 +16,7 @@ BrowserPpapiHostTest::BrowserPpapiHostTest()
std::string(),
base::FilePath(),
base::FilePath(),
- false,
- NULL));
+ false));
ppapi_host_->set_plugin_process_handle(base::GetCurrentProcessHandle());
}
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index f0cefc40396..39e778dfe6b 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -11,10 +11,12 @@
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_gamepad_host.h"
#include "content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
#include "content/browser/renderer_host/pepper/pepper_network_proxy_host.h"
#include "content/browser/renderer_host/pepper/pepper_print_settings_manager.h"
#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
#include "ppapi/host/message_filter_host.h"
@@ -36,18 +38,17 @@ const size_t kMaxSocketsAllowed = 1024;
bool CanCreateSocket() {
return
- PepperUDPSocketMessageFilter::GetNumInstances() +
- PepperTCPServerSocketMessageFilter::GetNumInstances() <
+ PepperTCPServerSocketMessageFilter::GetNumInstances() +
+ PepperTCPSocketMessageFilter::GetNumInstances() +
+ PepperUDPSocketMessageFilter::GetNumInstances() <
kMaxSocketsAllowed;
}
} // namespace
ContentBrowserPepperHostFactory::ContentBrowserPepperHostFactory(
- BrowserPpapiHostImpl* host,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
- : host_(host),
- pepper_message_filter_(pepper_message_filter) {
+ BrowserPpapiHostImpl* host)
+ : host_(host) {
}
ContentBrowserPepperHostFactory::~ContentBrowserPepperHostFactory() {
@@ -102,6 +103,15 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>(new PepperFileRefHost(
host_, instance, params.pp_resource(), file_system, internal_path));
}
+ case PpapiHostMsg_TCPSocket_Create::ID: {
+ ppapi::TCPSocketVersion version;
+ if (!UnpackMessage<PpapiHostMsg_TCPSocket_Create>(message, &version) ||
+ version == ppapi::TCP_SOCKET_VERSION_PRIVATE) {
+ return scoped_ptr<ResourceHost>();
+ }
+
+ return CreateNewTCPSocket(instance, params.pp_resource(), version);
+ }
case PpapiHostMsg_UDPSocket_Create::ID: {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> udp_socket(
@@ -155,8 +165,7 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
if (message.type() == PpapiHostMsg_TCPServerSocket_CreatePrivate::ID) {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> tcp_server_socket(
- new PepperTCPServerSocketMessageFilter(host_, instance, true,
- pepper_message_filter_));
+ new PepperTCPServerSocketMessageFilter(this, host_, instance, true));
return scoped_ptr<ResourceHost>(new MessageFilterHost(
host_->GetPpapiHost(), instance, params.pp_resource(),
tcp_server_socket));
@@ -164,6 +173,10 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
}
+ if (message.type() == PpapiHostMsg_TCPSocket_CreatePrivate::ID) {
+ return CreateNewTCPSocket(instance, params.pp_resource(),
+ ppapi::TCP_SOCKET_VERSION_PRIVATE);
+ }
if (message.type() == PpapiHostMsg_UDPSocket_CreatePrivate::ID) {
if (CanCreateSocket()) {
scoped_refptr<ResourceMessageFilter> udp_socket(
@@ -174,6 +187,10 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
}
+ if (message.type() == PpapiHostMsg_NetworkMonitor_Create::ID) {
+ return scoped_ptr<ResourceHost>(
+ new PepperNetworkMonitorHost(host_, instance, params.pp_resource()));
+ }
// Flash interfaces.
if (GetPermissions().HasPermission(ppapi::PERMISSION_FLASH)) {
@@ -191,6 +208,37 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>();
}
+scoped_ptr<ppapi::host::ResourceHost>
+ContentBrowserPepperHostFactory::CreateAcceptedTCPSocket(
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket) {
+ if (!CanCreateSocket())
+ return scoped_ptr<ResourceHost>();
+ scoped_refptr<ResourceMessageFilter> tcp_socket(
+ new PepperTCPSocketMessageFilter(host_, instance, version,
+ socket.Pass()));
+ return scoped_ptr<ResourceHost>(new MessageFilterHost(
+ host_->GetPpapiHost(), instance, 0, tcp_socket));
+}
+
+scoped_ptr<ppapi::host::ResourceHost>
+ContentBrowserPepperHostFactory::CreateNewTCPSocket(
+ PP_Instance instance,
+ PP_Resource resource,
+ ppapi::TCPSocketVersion version) {
+ if (!CanCreateSocket())
+ return scoped_ptr<ResourceHost>();
+
+ scoped_refptr<ResourceMessageFilter> tcp_socket(
+ new PepperTCPSocketMessageFilter(this, host_, instance, version));
+ if (!tcp_socket)
+ return scoped_ptr<ResourceHost>();
+
+ return scoped_ptr<ResourceHost>(new MessageFilterHost(
+ host_->GetPpapiHost(), instance, resource, tcp_socket));
+}
+
const ppapi::PpapiPermissions&
ContentBrowserPepperHostFactory::GetPermissions() const {
return host_->GetPpapiHost()->permissions();
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
index e39ec35d858..04267a32e8a 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
@@ -7,8 +7,11 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/socket/tcp_socket.h"
+#include "ppapi/c/pp_resource.h"
#include "ppapi/host/host_factory.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
namespace ppapi {
class PpapiPermissions;
@@ -21,11 +24,8 @@ class BrowserPpapiHostImpl;
class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
public:
// Non-owning pointer to the filter must outlive this class.
- ContentBrowserPepperHostFactory(
- BrowserPpapiHostImpl* host,
- // TODO (ygorshenin@): remove this once TCP sockets are
- // converted to the new design.
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ explicit ContentBrowserPepperHostFactory(BrowserPpapiHostImpl* host);
+
virtual ~ContentBrowserPepperHostFactory();
virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
@@ -34,14 +34,24 @@ class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
PP_Instance instance,
const IPC::Message& message) OVERRIDE;
+ // Creates ResourceHost for already accepted TCP |socket|. In the case of
+ // failure returns wrapped NULL.
+ scoped_ptr<ppapi::host::ResourceHost> CreateAcceptedTCPSocket(
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket);
+
private:
+ scoped_ptr<ppapi::host::ResourceHost> CreateNewTCPSocket(
+ PP_Instance instance,
+ PP_Resource resource,
+ ppapi::TCPSocketVersion version);
+
const ppapi::PpapiPermissions& GetPermissions() const;
// Non-owning pointer.
BrowserPpapiHostImpl* host_;
- scoped_refptr<PepperMessageFilter> pepper_message_filter_;
-
DISALLOW_COPY_AND_ASSIGN(ContentBrowserPepperHostFactory);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index 27ba37dfcca..096b908266f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -90,21 +90,16 @@ int32_t PepperExternalFileRefBackend::GetAbsolutePath(
ppapi::host::ReplyMessageContext reply_context) {
host_->SendReply(reply_context,
PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_.AsUTF8Unsafe()));
- return PP_OK;
+
+ // Use PP_OK_COMPLETIONPENDING instead of PP_OK since we've already sent our
+ // reply above.
+ return PP_OK_COMPLETIONPENDING;
}
fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
-std::string PepperExternalFileRefBackend::GetFileSystemURLSpec() const {
- return std::string();
-}
-
-base::FilePath PepperExternalFileRefBackend::GetExternalPath() const {
- return path_;
-}
-
int32_t PepperExternalFileRefBackend::CanRead() const {
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
CanReadFile(render_process_id_, path_)) {
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
index 994e9c291cd..cbfaf6ed511 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
@@ -41,8 +41,6 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
OVERRIDE;
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual std::string GetFileSystemURLSpec() const OVERRIDE;
- virtual base::FilePath GetExternalPath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
@@ -68,6 +66,8 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
scoped_refptr<base::TaskRunner> task_runner_;
base::WeakPtrFactory<PepperExternalFileRefBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperExternalFileRefBackend);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
index 5370af9d853..c38f8826534 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
@@ -62,9 +62,9 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
}
fs_type_ = fs_host->GetType();
- // TODO(teravest): Add support for isolated filesystems.
if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
- (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY)) {
+ (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) &&
+ (fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) {
DLOG(ERROR) << "Unsupported filesystem type: " << fs_type_;
return;
}
@@ -116,18 +116,6 @@ fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
-std::string PepperFileRefHost::GetFileSystemURLSpec() const {
- if (backend_)
- return backend_->GetFileSystemURLSpec();
- return std::string();
-}
-
-base::FilePath PepperFileRefHost::GetExternalPath() const {
- if (backend_)
- return backend_->GetExternalPath();
- return base::FilePath();
-}
-
int32_t PepperFileRefHost::CanRead() const {
if (backend_)
return backend_->CanRead();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
index 5d765764326..b97ff331ac0 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
@@ -42,8 +42,6 @@ class PepperFileRefBackend {
virtual int32_t GetAbsolutePath(
ppapi::host::ReplyMessageContext context) = 0;
virtual fileapi::FileSystemURL GetFileSystemURL() const = 0;
- virtual std::string GetFileSystemURLSpec() const = 0;
- virtual base::FilePath GetExternalPath() const = 0;
// Returns an error from the pp_errors.h enum.
virtual int32_t CanRead() const = 0;
@@ -79,10 +77,6 @@ class CONTENT_EXPORT PepperFileRefHost
PP_FileSystemType GetFileSystemType() const;
fileapi::FileSystemURL GetFileSystemURL() const;
- // Required to support FileIO.
- std::string GetFileSystemURLSpec() const;
- base::FilePath GetExternalPath() const;
-
int32_t CanRead() const;
int32_t CanWrite() const;
int32_t CanCreate() const;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index 1a10da77b83..fce371d8f99 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -58,16 +58,17 @@ PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
PP_FileSystemType type)
: ResourceHost(host->GetPpapiHost(), instance, resource),
browser_ppapi_host_(host),
- weak_factory_(this),
type_(type),
opened_(false),
fs_context_(NULL),
- called_open_(false) {
+ called_open_(false),
+ weak_factory_(this) {
}
PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
- if (fs_context_.get())
- fs_context_->operation_runner()->Shutdown();
+ // TODO(teravest): Create a FileSystemOperationRunner
+ // per-PepperFileSystemBrowserHost, force users of this FileSystem to use it,
+ // and call Shutdown() on it here.
}
int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
@@ -151,6 +152,18 @@ void PepperFileSystemBrowserHost::GotFileSystemContext(
fs_context_ = fs_context;
}
+void PepperFileSystemBrowserHost::GotIsolatedFileSystemContext(
+ ppapi::host::ReplyMessageContext reply_context,
+ scoped_refptr<fileapi::FileSystemContext> fs_context) {
+ fs_context_ = fs_context;
+ if (fs_context.get())
+ reply_context.params.set_result(PP_OK);
+ else
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FileSystem_InitIsolatedFileSystemReply());
+}
+
void PepperFileSystemBrowserHost::OpenFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error,
@@ -177,7 +190,22 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
url.GetOrigin(), fsid, "crxfs"));
opened_ = true;
- return PP_OK;
+
+ int render_process_id = 0;
+ int unused;
+ if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
+ &render_process_id,
+ &unused)) {
+ return PP_ERROR_FAILED;
+ }
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
+ base::Bind(&PepperFileSystemBrowserHost::GotIsolatedFileSystemContext,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()));
+ return PP_OK_COMPLETIONPENDING;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
index 3eb146e5b7e..ed648fb9938 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
@@ -47,6 +47,9 @@ class PepperFileSystemBrowserHost :
ppapi::host::ReplyMessageContext reply_context,
fileapi::FileSystemType file_system_type,
scoped_refptr<fileapi::FileSystemContext> fs_context);
+ void GotIsolatedFileSystemContext(
+ ppapi::host::ReplyMessageContext reply_context,
+ scoped_refptr<fileapi::FileSystemContext> fs_context);
void OpenFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error,
@@ -60,7 +63,6 @@ class PepperFileSystemBrowserHost :
const std::string& fsid);
BrowserPpapiHost* browser_ppapi_host_;
- base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_;
PP_FileSystemType type_;
bool opened_; // whether open is successful.
@@ -68,6 +70,8 @@ class PepperFileSystemBrowserHost :
scoped_refptr<fileapi::FileSystemContext> fs_context_;
bool called_open_; // whether open has been called.
+ base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperFileSystemBrowserHost);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
index e0e17b367ed..bdbdf871e27 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -132,7 +132,7 @@ int32_t PepperHostResolverMessageFilter::OnMsgResolve(
if (!render_view_host ||
!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
private_api_,
- request,
+ &request,
render_view_host)) {
return PP_ERROR_NOACCESS;
}
@@ -179,6 +179,7 @@ void PepperHostResolverMessageFilter::DoResolve(
new PepperLookupRequest<ReplyMessageContext>(
host_resolver,
request_info,
+ net::DEFAULT_PRIORITY,
bound_info.release(),
base::Bind(&PepperHostResolverMessageFilter::OnLookupFinished, this));
lookup_request->Start();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index 337807d34e1..3b8c801ec1a 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -63,27 +63,16 @@ fileapi::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
if (!fs_url_.is_valid() && fs_host_.get() && fs_host_->IsOpened()) {
GURL fs_path = fs_host_->GetRootUrl().Resolve(
net::EscapePath(path_.substr(1)));
- fs_url_ = GetFileSystemContext()->CrackURL(fs_path);
+ scoped_refptr<fileapi::FileSystemContext> fs_context =
+ GetFileSystemContext();
+ if (fs_context.get())
+ fs_url_ = fs_context->CrackURL(fs_path);
}
return fs_url_;
}
-std::string PepperInternalFileRefBackend::GetFileSystemURLSpec() const {
- if (fs_host_.get() && fs_host_->IsOpened() &&
- fs_host_->GetRootUrl().is_valid()) {
- return fs_host_->GetRootUrl().Resolve(
- net::EscapePath(path_.substr(1))).spec();
- }
- return std::string();
-}
-
-base::FilePath PepperInternalFileRefBackend::GetExternalPath() const {
- return base::FilePath();
-}
-
scoped_refptr<fileapi::FileSystemContext>
PepperInternalFileRefBackend::GetFileSystemContext() const {
- // TODO(teravest): Make this work for CRX file systems.
if (!fs_host_.get())
return NULL;
return fs_host_->GetFileSystemContext();
@@ -221,7 +210,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
context.params.set_result(ppapi::PlatformFileErrorToPepperError(error));
- std::vector<ppapi::FileRef_CreateInfo> infos;
+ std::vector<ppapi::FileRefCreateInfo> infos;
std::vector<PP_FileType> file_types;
if (error == base::PLATFORM_FILE_OK && fs_host_.get()) {
std::string dir_path = path_;
@@ -235,7 +224,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
else
file_types.push_back(PP_FILETYPE_REGULAR);
- ppapi::FileRef_CreateInfo info;
+ ppapi::FileRefCreateInfo info;
info.file_system_type = fs_type_;
info.file_system_plugin_resource = fs_host_->pp_resource();
std::string path =
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
index fb8a6cf7603..81d6ab624cd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
@@ -46,8 +46,6 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
OVERRIDE;
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual std::string GetFileSystemURLSpec() const OVERRIDE;
- virtual base::FilePath GetExternalPath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
@@ -82,6 +80,8 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
mutable fileapi::FileSystemURL fs_url_;
base::WeakPtrFactory<PepperInternalFileRefBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperInternalFileRefBackend);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h b/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
index bcb9a60203f..da116fd640c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_lookup_request.h
@@ -24,20 +24,23 @@ class PepperLookupRequest {
// callback, when lookup will finish.
PepperLookupRequest(net::HostResolver* resolver,
const net::HostResolver::RequestInfo& request_info,
+ net::RequestPriority priority,
T* bound_info,
const LookupRequestCallback& callback)
: resolver_(resolver),
request_info_(request_info),
+ priority_(priority),
bound_info_(bound_info),
- callback_(callback) {
- }
+ callback_(callback) {}
void Start() {
- int result = resolver_.Resolve(
- request_info_, &addresses_,
- base::Bind(&PepperLookupRequest<T>::OnLookupFinished,
- base::Unretained(this)),
- net::BoundNetLog());
+ int result =
+ resolver_.Resolve(request_info_,
+ priority_,
+ &addresses_,
+ base::Bind(&PepperLookupRequest<T>::OnLookupFinished,
+ base::Unretained(this)),
+ net::BoundNetLog());
if (result != net::ERR_IO_PENDING)
OnLookupFinished(result);
}
@@ -50,6 +53,7 @@ class PepperLookupRequest {
net::SingleRequestHostResolver resolver_;
net::HostResolver::RequestInfo request_info_;
+ net::RequestPriority priority_;
scoped_ptr<T> bound_info_;
LookupRequestCallback callback_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
index 717de350dc7..6434729b734 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
@@ -4,118 +4,20 @@
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/worker_pool.h"
-#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
-#include "content/browser/renderer_host/pepper/pepper_tcp_socket.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/common/pepper_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/resource_context.h"
#include "content/public/common/content_client.h"
-#include "net/base/address_family.h"
-#include "net/base/address_list.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/sys_addrinfo.h"
-#include "net/cert/cert_verifier.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/api_id.h"
-#include "ppapi/shared_impl/private/net_address_private_impl.h"
-#include "ppapi/shared_impl/socket_option_data.h"
-
-using ppapi::NetAddressPrivateImpl;
namespace content {
-namespace {
-
-const size_t kMaxSocketsAllowed = 1024;
-const uint32 kInvalidSocketID = 0;
-
-} // namespace
-PepperMessageFilter::PepperMessageFilter(int process_id,
- BrowserContext* browser_context)
- : plugin_type_(PLUGIN_TYPE_IN_PROCESS),
- permissions_(),
- process_id_(process_id),
- external_plugin_render_view_id_(0),
- resource_context_(browser_context->GetResourceContext()),
- host_resolver_(NULL),
- next_socket_id_(1) {
- DCHECK(browser_context);
- // Keep BrowserContext data in FILE-thread friendly storage.
- browser_path_ = browser_context->GetPath();
- incognito_ = browser_context->IsOffTheRecord();
- DCHECK(resource_context_);
-}
-
-PepperMessageFilter::PepperMessageFilter(
- const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver)
- : plugin_type_(PLUGIN_TYPE_OUT_OF_PROCESS),
- permissions_(permissions),
- process_id_(0),
- external_plugin_render_view_id_(0),
- resource_context_(NULL),
- host_resolver_(host_resolver),
- next_socket_id_(1),
- incognito_(false) {
- DCHECK(host_resolver);
-}
-
-PepperMessageFilter::PepperMessageFilter(
- const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver,
- int process_id,
- int render_view_id)
- : plugin_type_(PLUGIN_TYPE_EXTERNAL_PLUGIN),
- permissions_(permissions),
- process_id_(process_id),
- external_plugin_render_view_id_(render_view_id),
- resource_context_(NULL),
- host_resolver_(host_resolver),
- next_socket_id_(1) {
- DCHECK(host_resolver);
-}
+PepperMessageFilter::PepperMessageFilter() {}
+PepperMessageFilter::~PepperMessageFilter() {}
bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok)
- // TCP messages.
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Create, OnTCPCreate)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_CreatePrivate,
- OnTCPCreatePrivate)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Connect, OnTCPConnect)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress,
- OnTCPConnectWithNetAddress)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SSLHandshake,
- OnTCPSSLHandshake)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Read, OnTCPRead)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Write, OnTCPWrite)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Disconnect, OnTCPDisconnect)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SetOption, OnTCPSetOption)
-
- // NetworkMonitor messages.
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Start,
- OnNetworkMonitorStart)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Stop,
- OnNetworkMonitorStop)
-
// X509 certificate messages.
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBX509Certificate_ParseDER,
OnX509CertificateParseDER);
@@ -125,367 +27,14 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
return handled;
}
-void PepperMessageFilter::OnIPAddressChanged() {
- GetAndSendNetworkList();
-}
-
-net::HostResolver* PepperMessageFilter::GetHostResolver() {
- return resource_context_ ?
- resource_context_->GetHostResolver() : host_resolver_;
-}
-
-net::CertVerifier* PepperMessageFilter::GetCertVerifier() {
- if (!cert_verifier_)
- cert_verifier_.reset(net::CertVerifier::CreateDefault());
-
- return cert_verifier_.get();
-}
-
-net::TransportSecurityState* PepperMessageFilter::GetTransportSecurityState() {
- if (!transport_security_state_)
- transport_security_state_.reset(new net::TransportSecurityState);
-
- return transport_security_state_.get();
-}
-
-uint32 PepperMessageFilter::AddAcceptedTCPSocket(
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- net::StreamSocket* socket) {
- scoped_ptr<net::StreamSocket> s(socket);
-
- uint32 tcp_socket_id = GenerateSocketID();
- if (tcp_socket_id != kInvalidSocketID) {
- // Currently all TCP sockets created this way correspond to
- // PPB_TCPSocket_Private.
- tcp_sockets_[tcp_socket_id] = linked_ptr<PepperTCPSocket>(
- new PepperTCPSocket(this,
- routing_id,
- plugin_dispatcher_id,
- tcp_socket_id,
- s.release(),
- true /* private_api */));
- }
- return tcp_socket_id;
-}
-
-PepperMessageFilter::~PepperMessageFilter() {
- if (!network_monitor_ids_.empty())
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
-}
-
-void PepperMessageFilter::OnTCPCreate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id) {
- CreateTCPSocket(routing_id, plugin_dispatcher_id, false, socket_id);
-}
-
-void PepperMessageFilter::OnTCPCreatePrivate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id) {
- CreateTCPSocket(routing_id, plugin_dispatcher_id, true, socket_id);
-}
-
-void PepperMessageFilter::OnTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // This is only supported by PPB_TCPSocket_Private.
- if (!iter->second->private_api()) {
- NOTREACHED();
- return;
- }
-
- content::SocketPermissionRequest params(
- content::SocketPermissionRequest::TCP_CONNECT, host, port);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
- routing_id, params, true /* private_api */),
- base::Bind(&PepperMessageFilter::DoTCPConnect, this,
- routing_id, socket_id, host, port));
-}
-
-void PepperMessageFilter::DoTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port,
- bool allowed) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- // Due to current permission check process (IO -> UI -> IO) some
- // calls to the TCP socket interface can be intermixed (like
- // Connect and Close). So, NOTREACHED() is not appropriate here.
- return;
- }
-
- if (routing_id == iter->second->routing_id() && allowed)
- iter->second->Connect(host, port);
- else
- iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
-}
-
-void PepperMessageFilter::OnTCPConnectWithNetAddress(
- int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- content::SocketPermissionRequest params =
- pepper_socket_utils::CreateSocketPermissionRequest(
- content::SocketPermissionRequest::TCP_CONNECT, net_addr);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
- routing_id, params, iter->second->private_api()),
- base::Bind(&PepperMessageFilter::DoTCPConnectWithNetAddress, this,
- routing_id, socket_id, net_addr));
-}
-
-void PepperMessageFilter::DoTCPConnectWithNetAddress(
- int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr,
- bool allowed) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- // Due to current permission check process (IO -> UI -> IO) some
- // calls to the TCP socket interface can be intermixed (like
- // ConnectWithNetAddress and Close). So, NOTREACHED() is not
- // appropriate here.
- return;
- }
-
- if (routing_id == iter->second->routing_id() && allowed)
- iter->second->ConnectWithNetAddress(net_addr);
- else
- iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
-}
-
-void PepperMessageFilter::OnTCPSSLHandshake(
- uint32 socket_id,
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // This is only supported by PPB_TCPSocket_Private.
- if (!iter->second->private_api()) {
- NOTREACHED();
- return;
- }
-
- iter->second->SSLHandshake(server_name, server_port, trusted_certs,
- untrusted_certs);
-}
-
-void PepperMessageFilter::OnTCPRead(uint32 socket_id, int32_t bytes_to_read) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->Read(bytes_to_read);
-}
-
-void PepperMessageFilter::OnTCPWrite(uint32 socket_id,
- const std::string& data) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->Write(data);
-}
-
-void PepperMessageFilter::OnTCPDisconnect(uint32 socket_id) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- // Destroying the TCPSocket instance will cancel any pending completion
- // callback. From this point on, there won't be any messages associated with
- // this socket sent to the plugin side.
- tcp_sockets_.erase(iter);
-}
-
-void PepperMessageFilter::OnTCPSetOption(uint32 socket_id,
- PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value) {
- TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
- if (iter == tcp_sockets_.end()) {
- NOTREACHED();
- return;
- }
-
- iter->second->SetOption(name, value);
-}
-
-void PepperMessageFilter::OnNetworkMonitorStart(uint32 plugin_dispatcher_id) {
- // Support all in-process plugins, and ones with "private" permissions.
- if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
- !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
- return;
- }
-
- if (network_monitor_ids_.empty())
- net::NetworkChangeNotifier::AddIPAddressObserver(this);
-
- network_monitor_ids_.insert(plugin_dispatcher_id);
- GetAndSendNetworkList();
-}
-
-void PepperMessageFilter::OnNetworkMonitorStop(uint32 plugin_dispatcher_id) {
- // Support all in-process plugins, and ones with "private" permissions.
- if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
- !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
- return;
- }
-
- network_monitor_ids_.erase(plugin_dispatcher_id);
- if (network_monitor_ids_.empty())
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
-}
-
void PepperMessageFilter::OnX509CertificateParseDER(
const std::vector<char>& der,
bool* succeeded,
ppapi::PPB_X509Certificate_Fields* result) {
if (der.size() == 0)
*succeeded = false;
- *succeeded = PepperTCPSocket::GetCertificateFields(&der[0], der.size(),
- result);
-}
-
-uint32 PepperMessageFilter::GenerateSocketID() {
- // TODO(yzshen): Change to use Pepper resource ID as socket ID.
- //
- // Generate a socket ID. For each process which sends us socket requests, IDs
- // of living sockets must be unique, to each socket type.
- //
- // However, it is safe to generate IDs based on the internal state of a single
- // PepperSocketMessageHandler object, because for each plugin or renderer
- // process, there is at most one PepperMessageFilter (in other words, at most
- // one PepperSocketMessageHandler) talking to it.
- if (tcp_sockets_.size() >= kMaxSocketsAllowed)
- return kInvalidSocketID;
-
- uint32 socket_id = kInvalidSocketID;
- do {
- // Although it is unlikely, make sure that we won't cause any trouble when
- // the counter overflows.
- socket_id = next_socket_id_++;
- } while (socket_id == kInvalidSocketID ||
- tcp_sockets_.find(socket_id) != tcp_sockets_.end());
-
- return socket_id;
-}
-
-bool PepperMessageFilter::CanUseSocketAPIs(
- int32 render_id,
- const content::SocketPermissionRequest& params,
- bool private_api) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // External plugins always get their own PepperMessageFilter, initialized with
- // a render view id. Use this instead of the one that came with the message,
- // which is actually an API ID.
- bool external_plugin = false;
- if (plugin_type_ == PLUGIN_TYPE_EXTERNAL_PLUGIN) {
- external_plugin = true;
- render_id = external_plugin_render_view_id_;
- }
-
- RenderViewHostImpl* render_view_host =
- RenderViewHostImpl::FromID(process_id_, render_id);
-
- return pepper_socket_utils::CanUseSocketAPIs(external_plugin,
- private_api,
- params,
- render_view_host);
-}
-
-void PepperMessageFilter::GetAndSendNetworkList() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- BrowserThread::PostBlockingPoolTask(
- FROM_HERE, base::Bind(&PepperMessageFilter::DoGetNetworkList, this));
-}
-
-void PepperMessageFilter::DoGetNetworkList() {
- scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList());
- net::GetNetworkList(list.get());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&PepperMessageFilter::SendNetworkList,
- this, base::Passed(&list)));
-}
-
-void PepperMessageFilter::SendNetworkList(
- scoped_ptr<net::NetworkInterfaceList> list) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- scoped_ptr< ::ppapi::NetworkList> list_copy(
- new ::ppapi::NetworkList(list->size()));
- for (size_t i = 0; i < list->size(); ++i) {
- const net::NetworkInterface& network = list->at(i);
- ::ppapi::NetworkInfo& network_copy = list_copy->at(i);
- network_copy.name = network.name;
-
- network_copy.addresses.resize(1, NetAddressPrivateImpl::kInvalidNetAddress);
- bool result = NetAddressPrivateImpl::IPEndPointToNetAddress(
- network.address, 0, &(network_copy.addresses[0]));
- DCHECK(result);
-
- // TODO(sergeyu): Currently net::NetworkInterfaceList provides
- // only name and one IP address. Add all other fields and copy
- // them here.
- network_copy.type = PP_NETWORKLIST_UNKNOWN;
- network_copy.state = PP_NETWORKLIST_UP;
- network_copy.display_name = network.name;
- network_copy.mtu = 0;
- }
- for (NetworkMonitorIdSet::iterator it = network_monitor_ids_.begin();
- it != network_monitor_ids_.end(); ++it) {
- Send(new PpapiMsg_PPBNetworkMonitor_NetworkList(
- ppapi::API_ID_PPB_NETWORKMANAGER_PRIVATE, *it, *list_copy));
- }
-}
-
-void PepperMessageFilter::CreateTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- bool private_api,
- uint32* socket_id) {
- *socket_id = GenerateSocketID();
- if (*socket_id == kInvalidSocketID)
- return;
-
- tcp_sockets_[*socket_id] = linked_ptr<PepperTCPSocket>(
- new PepperTCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id,
- private_api));
+ *succeeded =
+ pepper_socket_utils::GetCertificateFields(&der[0], der.size(), result);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
index 11c8fbd4902..3f5010ed40e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
@@ -5,223 +5,35 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_MESSAGE_FILTER_H_
-#include <map>
-#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
-#include "base/process/process.h"
#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/process_type.h"
-#include "net/base/net_util.h"
-#include "net/base/network_change_notifier.h"
-#include "net/http/transport_security_state.h"
-#include "net/socket/stream_socket.h"
-#include "net/ssl/ssl_config_service.h"
-#include "ppapi/c/pp_resource.h"
-#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/ppb_tcp_socket.h"
-#include "ppapi/c/private/ppb_flash.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/shared_impl/ppapi_permissions.h"
-
-struct PP_NetAddress_Private;
-
-namespace base {
-class ListValue;
-}
-
-namespace net {
-class CertVerifier;
-class HostResolver;
-}
namespace ppapi {
class PPB_X509Certificate_Fields;
-class SocketOptionData;
}
namespace content {
-class BrowserContext;
-class PepperTCPSocket;
-class ResourceContext;
-// This class is used in two contexts, both supporting PPAPI plugins. The first
-// is on the renderer->browser channel, to handle requests from in-process
-// PPAPI plugins and any requests that the PPAPI implementation code in the
-// renderer needs to make. The second is on the plugin->browser channel to
-// handle requests that out-of-process plugins send directly to the browser.
-class PepperMessageFilter
- : public BrowserMessageFilter,
- public net::NetworkChangeNotifier::IPAddressObserver {
+// Message filter that handles IPC for PPB_X509Certificate_Private.
+class PepperMessageFilter : public BrowserMessageFilter {
public:
- // Constructor when used in the context of a render process.
- PepperMessageFilter(int process_id,
- BrowserContext* browser_context);
-
- // Constructor when used in the context of a PPAPI process..
- PepperMessageFilter(const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver);
-
- // Constructor when used in the context of an external plugin, i.e. created by
- // the embedder using BrowserPpapiHost::CreateExternalPluginProcess.
- PepperMessageFilter(const ppapi::PpapiPermissions& permissions,
- net::HostResolver* host_resolver,
- int process_id,
- int render_view_id);
+ PepperMessageFilter();
// BrowserMessageFilter methods.
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
- // net::NetworkChangeNotifier::IPAddressObserver interface.
- virtual void OnIPAddressChanged() OVERRIDE;
-
- // Returns the host resolver (it may come from the resource context or the
- // host_resolver_ member).
- net::HostResolver* GetHostResolver();
-
- net::CertVerifier* GetCertVerifier();
- net::TransportSecurityState* GetTransportSecurityState();
-
- // Adds already accepted socket to the internal TCP sockets table. Takes
- // ownership over |socket|. In the case of failure (full socket table)
- // returns 0 and deletes |socket|. Otherwise, returns generated ID for
- // |socket|.
- uint32 AddAcceptedTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- net::StreamSocket* socket);
-
- const net::SSLConfig& ssl_config() { return ssl_config_; }
-
protected:
virtual ~PepperMessageFilter();
private:
- struct OnConnectTcpBoundInfo {
- int routing_id;
- int request_id;
- };
-
- // Containers for sockets keyed by socked_id.
- typedef std::map<uint32, linked_ptr<PepperTCPSocket> > TCPSocketMap;
-
- // Set of disptachers ID's that have subscribed for NetworkMonitor
- // notifications.
- typedef std::set<uint32> NetworkMonitorIdSet;
-
- void OnGetLocalTimeZoneOffset(base::Time t, double* result);
-
- void OnTCPCreate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id);
- void OnTCPCreatePrivate(int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32* socket_id);
- void OnTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port);
- void OnTCPConnectWithNetAddress(int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr);
- void OnTCPSSLHandshake(
- uint32 socket_id,
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs);
- void OnTCPRead(uint32 socket_id, int32_t bytes_to_read);
- void OnTCPWrite(uint32 socket_id, const std::string& data);
- void OnTCPDisconnect(uint32 socket_id);
- void OnTCPSetOption(uint32 socket_id,
- PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value);
-
- void OnNetworkMonitorStart(uint32 plugin_dispatcher_id);
- void OnNetworkMonitorStop(uint32 plugin_dispatcher_id);
-
- void DoTCPConnect(int32 routing_id,
- uint32 socket_id,
- const std::string& host,
- uint16_t port,
- bool allowed);
- void DoTCPConnectWithNetAddress(int32 routing_id,
- uint32 socket_id,
- const PP_NetAddress_Private& net_addr,
- bool allowed);
void OnX509CertificateParseDER(const std::vector<char>& der,
bool* succeeded,
ppapi::PPB_X509Certificate_Fields* result);
- void OnUpdateActivity();
-
- uint32 GenerateSocketID();
-
- // Return true if render with given ID can use socket APIs.
- bool CanUseSocketAPIs(int32 render_id,
- const content::SocketPermissionRequest& params,
- bool private_api);
-
- void GetAndSendNetworkList();
- void DoGetNetworkList();
- void SendNetworkList(scoped_ptr<net::NetworkInterfaceList> list);
- void CreateTCPSocket(int32 routing_id,
- uint32 plugin_dispatcher_id,
- bool private_api,
- uint32* socket_id);
- enum PluginType {
- PLUGIN_TYPE_IN_PROCESS,
- PLUGIN_TYPE_OUT_OF_PROCESS,
- // External plugin means it was created through
- // BrowserPpapiHost::CreateExternalPluginProcess.
- PLUGIN_TYPE_EXTERNAL_PLUGIN,
- };
-
- PluginType plugin_type_;
-
- // When attached to an out-of-process plugin (be it native or NaCl) this
- // will have the Pepper permissions for the plugin. When attached to the
- // renderer channel, this will have no permissions listed (since there may
- // be many plugins sharing this channel).
- ppapi::PpapiPermissions permissions_;
-
- // Render process ID.
- int process_id_;
-
- // External plugin RenderView id to determine private API access. Normally, we
- // handle messages coming from multiple RenderViews, but external plugins
- // always creates a new PepperMessageFilter for each RenderView.
- int external_plugin_render_view_id_;
-
- // When non-NULL, this should be used instead of the host_resolver_.
- ResourceContext* const resource_context_;
-
- // When non-NULL, this should be used instead of the resource_context_. Use
- // GetHostResolver instead of accessing directly.
- net::HostResolver* host_resolver_;
-
- // The default SSL configuration settings are used, as opposed to Chrome's SSL
- // settings.
- net::SSLConfig ssl_config_;
- // This is lazily created. Users should use GetCertVerifier to retrieve it.
- scoped_ptr<net::CertVerifier> cert_verifier_;
- // This is lazily created. Users should use GetTransportSecurityState to
- // retrieve it.
- scoped_ptr<net::TransportSecurityState> transport_security_state_;
-
- uint32 next_socket_id_;
-
- TCPSocketMap tcp_sockets_;
-
- NetworkMonitorIdSet network_monitor_ids_;
-
- base::FilePath browser_path_;
- bool incognito_;
DISALLOW_COPY_AND_ASSIGN(PepperMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
new file mode 100644
index 00000000000..b53a60b779b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_network_monitor_host.h"
+
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/socket_permission_request.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+
+
+namespace content {
+
+namespace {
+
+bool CanUseNetworkMonitor(bool external_plugin,
+ int render_process_id,
+ int render_view_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ SocketPermissionRequest request = SocketPermissionRequest(
+ SocketPermissionRequest::NETWORK_STATE, std::string(), 0);
+ return pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin, false /* private_api */, &request, render_process_id,
+ render_view_id);
+}
+
+scoped_ptr<net::NetworkInterfaceList> GetNetworkList() {
+ scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList());
+ net::GetNetworkList(list.get());
+ return list.Pass();
+}
+
+} // namespace
+
+PepperNetworkMonitorHost::PepperNetworkMonitorHost(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ weak_factory_(this) {
+ int render_process_id;
+ int render_view_id;
+ host->GetRenderViewIDsForInstance(instance,
+ &render_process_id,
+ &render_view_id);
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CanUseNetworkMonitor, host->external_plugin(),
+ render_process_id, render_view_id),
+ base::Bind(&PepperNetworkMonitorHost::OnPermissionCheckResult,
+ weak_factory_.GetWeakPtr()));
+}
+
+PepperNetworkMonitorHost::~PepperNetworkMonitorHost() {
+ net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+}
+
+void PepperNetworkMonitorHost::OnIPAddressChanged() {
+ GetAndSendNetworkList();
+}
+
+void PepperNetworkMonitorHost::OnPermissionCheckResult(
+ bool can_use_network_monitor) {
+ if (!can_use_network_monitor) {
+ host()->SendUnsolicitedReply(pp_resource(),
+ PpapiPluginMsg_NetworkMonitor_Forbidden());
+ return;
+ }
+
+ net::NetworkChangeNotifier::AddIPAddressObserver(this);
+ GetAndSendNetworkList();
+}
+
+void PepperNetworkMonitorHost::GetAndSendNetworkList() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Call GetNetworkList() on a thread that allows blocking IO.
+ base::PostTaskAndReplyWithResult(
+ BrowserThread::GetBlockingPool(), FROM_HERE,
+ base::Bind(&GetNetworkList),
+ base::Bind(&PepperNetworkMonitorHost::SendNetworkList,
+ weak_factory_.GetWeakPtr()));
+}
+
+void PepperNetworkMonitorHost::SendNetworkList(
+ scoped_ptr<net::NetworkInterfaceList> list) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ scoped_ptr<ppapi::proxy::SerializedNetworkList> list_copy(
+ new ppapi::proxy::SerializedNetworkList(list->size()));
+ for (size_t i = 0; i < list->size(); ++i) {
+ const net::NetworkInterface& network = list->at(i);
+ ppapi::proxy::SerializedNetworkInfo& network_copy = list_copy->at(i);
+ network_copy.name = network.name;
+
+ network_copy.addresses.resize(
+ 1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
+ bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
+ network.address, 0, &(network_copy.addresses[0]));
+ DCHECK(result);
+
+ // TODO(sergeyu): Currently net::NetworkInterfaceList provides
+ // only name and one IP address. Add all other fields and copy
+ // them here.
+ network_copy.type = PP_NETWORKLIST_TYPE_UNKNOWN;
+ network_copy.state = PP_NETWORKLIST_STATE_UP;
+ network_copy.display_name = network.name;
+ network_copy.mtu = 0;
+ }
+ host()->SendUnsolicitedReply(
+ pp_resource(), PpapiPluginMsg_NetworkMonitor_NetworkList(*list_copy));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
new file mode 100644
index 00000000000..e27f8a2ac21
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "net/base/net_util.h"
+#include "net/base/network_change_notifier.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHostImpl;
+
+// The host for PPB_NetworkMonitor. This class lives on the IO thread.
+class CONTENT_EXPORT PepperNetworkMonitorHost
+ : public ppapi::host::ResourceHost,
+ public net::NetworkChangeNotifier::IPAddressObserver {
+ public:
+ PepperNetworkMonitorHost(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource);
+
+ virtual ~PepperNetworkMonitorHost();
+
+ // net::NetworkChangeNotifier::IPAddressObserver interface.
+ virtual void OnIPAddressChanged() OVERRIDE;
+
+ private:
+ void OnPermissionCheckResult(bool can_use_network_monitor);
+
+ void GetAndSendNetworkList();
+ void SendNetworkList(scoped_ptr<net::NetworkInterfaceList> list);
+
+ ppapi::host::ReplyMessageContext reply_context_;
+
+ base::WeakPtrFactory<PepperNetworkMonitorHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperNetworkMonitorHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_NETWORK_MONITOR_HOST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 6042badfc92..13f0fc3733f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -84,7 +84,7 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
result.is_allowed = pepper_socket_utils::CanUseSocketAPIs(
is_external_plugin,
false /* is_private_api */,
- request,
+ &request,
render_view_host);
}
return result;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index a5b95ceb223..e4c8aa71dc1 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -16,6 +16,7 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/resource_message_params.h"
namespace content {
@@ -28,8 +29,7 @@ PepperRendererConnection::PepperRendererConnection(int render_process_id)
"",
base::FilePath(),
base::FilePath(),
- false,
- NULL));
+ false));
}
PepperRendererConnection::~PepperRendererConnection() {
@@ -72,10 +72,8 @@ bool PepperRendererConnection::OnMessageReceived(const IPC::Message& msg,
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(PepperRendererConnection, msg, *message_was_ok)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostFromHost,
- OnMsgCreateResourceHostFromHost)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRenderer,
- OnMsgFileRefGetInfoForRenderer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostsFromHost,
+ OnMsgCreateResourceHostsFromHost)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateInProcessInstance,
OnMsgDidCreateInProcessInstance)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteInProcessInstance,
@@ -86,79 +84,48 @@ bool PepperRendererConnection::OnMessageReceived(const IPC::Message& msg,
return handled;
}
-void PepperRendererConnection::OnMsgCreateResourceHostFromHost(
+void PepperRendererConnection::OnMsgCreateResourceHostsFromHost(
int routing_id,
int child_process_id,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& nested_msg) {
+ const std::vector<IPC::Message>& nested_msgs) {
BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
- int pending_resource_host_id;
+ std::vector<int> pending_resource_host_ids(nested_msgs.size(), 0);
if (!host) {
DLOG(ERROR) << "Invalid plugin process ID.";
- pending_resource_host_id = 0;
} else {
- // FileRef_CreateExternal is only permitted from the renderer. Because of
- // this, we handle this message here and not in
- // content_browser_pepper_host_factory.cc.
- scoped_ptr<ppapi::host::ResourceHost> resource_host;
- if (host->IsValidInstance(instance)) {
- if (nested_msg.type() == PpapiHostMsg_FileRef_CreateExternal::ID) {
- base::FilePath external_path;
- if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateExternal>(
- nested_msg, &external_path)) {
- resource_host.reset(new PepperFileRefHost(
- host, instance, params.pp_resource(), external_path));
+ for (size_t i = 0; i < nested_msgs.size(); ++i) {
+ // FileRef_CreateExternal is only permitted from the renderer. Because of
+ // this, we handle this message here and not in
+ // content_browser_pepper_host_factory.cc.
+ scoped_ptr<ppapi::host::ResourceHost> resource_host;
+ if (host->IsValidInstance(instance)) {
+ if (nested_msgs[i].type() == PpapiHostMsg_FileRef_CreateExternal::ID) {
+ base::FilePath external_path;
+ if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateExternal>(
+ nested_msgs[i], &external_path)) {
+ resource_host.reset(new PepperFileRefHost(
+ host, instance, params.pp_resource(), external_path));
+ }
}
}
- }
-
- if (!resource_host.get()) {
- resource_host = host->GetPpapiHost()->CreateResourceHost(params,
- instance,
- nested_msg);
- }
- pending_resource_host_id =
- host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
- }
-
- Send(new PpapiHostMsg_CreateResourceHostFromHostReply(
- routing_id, params.sequence(), pending_resource_host_id));
-}
-void PepperRendererConnection::OnMsgFileRefGetInfoForRenderer(
- int routing_id,
- int child_process_id,
- int32_t sequence,
- const std::vector<PP_Resource>& resources) {
- std::vector<PP_Resource> out_resources;
- std::vector<PP_FileSystemType> fs_types;
- std::vector<std::string> file_system_url_specs;
- std::vector<base::FilePath> external_paths;
+ if (!resource_host.get()) {
+ resource_host = host->GetPpapiHost()->CreateResourceHost(
+ params, instance, nested_msgs[i]);
+ }
- BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
- if (host) {
- for (size_t i = 0; i < resources.size(); ++i) {
- ppapi::host::ResourceHost* resource_host =
- host->GetPpapiHost()->GetResourceHost(resources[i]);
- if (resource_host && resource_host->IsFileRefHost()) {
- PepperFileRefHost* file_ref_host =
- static_cast<PepperFileRefHost*>(resource_host);
- out_resources.push_back(resources[i]);
- fs_types.push_back(file_ref_host->GetFileSystemType());
- file_system_url_specs.push_back(file_ref_host->GetFileSystemURLSpec());
- external_paths.push_back(file_ref_host->GetExternalPath());
+ if (resource_host.get()) {
+ pending_resource_host_ids[i] =
+ host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
}
}
}
- Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
- routing_id,
- sequence,
- out_resources,
- fs_types,
- file_system_url_specs,
- external_paths));
+
+ Send(new PpapiHostMsg_CreateResourceHostsFromHostReply(
+ routing_id, params.sequence(), pending_resource_host_ids));
}
void PepperRendererConnection::OnMsgDidCreateInProcessInstance(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 43923465d0b..157827a9cfd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_RENDERER_CONNECTION_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_RENDERER_CONNECTION_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -45,18 +47,12 @@ class PepperRendererConnection : public BrowserMessageFilter {
// PepperRendererConnection, which serves as the host for in-process plugins.
BrowserPpapiHostImpl* GetHostForChildProcess(int child_process_id) const;
- void OnMsgCreateResourceHostFromHost(
+ void OnMsgCreateResourceHostsFromHost(
int routing_id,
int child_process_id,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& nested_msg);
-
- void OnMsgFileRefGetInfoForRenderer(
- int routing_id,
- int child_process_id,
- int32_t sequence_num,
- const std::vector<PP_Resource>& resources);
+ const std::vector<IPC::Message>& nested_msgs);
void OnMsgDidCreateInProcessInstance(
PP_Instance instance,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
index 5402823f01e..5816ce4831f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
@@ -10,8 +10,18 @@
namespace content {
-bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
- const base::FilePath& file) {
+namespace {
+
+template <typename CanRead, typename CanWrite,
+ typename CanCreate, typename CanCreateWrite,
+ typename FileID>
+bool CanOpenFileWithPepperFlags(CanRead can_read,
+ CanWrite can_write,
+ CanCreate can_create,
+ CanCreateWrite can_create_write,
+ int pp_open_flags,
+ int child_id,
+ const FileID& file) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -22,33 +32,53 @@ bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
bool pp_exclusive = !!(pp_open_flags & PP_FILEOPENFLAG_EXCLUSIVE);
bool pp_append = !!(pp_open_flags & PP_FILEOPENFLAG_APPEND);
- if (pp_read && !policy->CanReadFile(child_id, file))
+ if (pp_read && !(policy->*can_read)(child_id, file))
return false;
- if (pp_write && !policy->CanWriteFile(child_id, file))
+ if (pp_write && !(policy->*can_write)(child_id, file))
return false;
- if (pp_append) {
- // Given ChildSecurityPolicyImpl's current definition of permissions,
- // APPEND is never supported.
+ // TODO(tommycli): Maybe tighten up required permission. crbug.com/284792
+ if (pp_append && !(policy->*can_create_write)(child_id, file))
return false;
- }
if (pp_truncate && !pp_write)
return false;
if (pp_create) {
if (pp_exclusive) {
- return policy->CanCreateFile(child_id, file);
+ return (policy->*can_create)(child_id, file);
} else {
// Asks for too much, but this is the only grant that allows overwrite.
- return policy->CanCreateWriteFile(child_id, file);
+ return (policy->*can_create_write)(child_id, file);
}
} else if (pp_truncate) {
- return policy->CanCreateWriteFile(child_id, file);
+ return (policy->*can_create_write)(child_id, file);
}
return true;
}
+}
+
+bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
+ const base::FilePath& file) {
+ return CanOpenFileWithPepperFlags(
+ &ChildProcessSecurityPolicyImpl::CanReadFile,
+ &ChildProcessSecurityPolicyImpl::CanWriteFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateWriteFile,
+ pp_open_flags, child_id, file);
+}
+
+bool CanOpenFileSystemURLWithPepperFlags(int pp_open_flags, int child_id,
+ const fileapi::FileSystemURL& url) {
+ return CanOpenFileWithPepperFlags(
+ &ChildProcessSecurityPolicyImpl::CanReadFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateWriteFileSystemFile,
+ pp_open_flags, child_id, url);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
index 4a3cea5874a..d0a39831324 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
@@ -7,15 +7,23 @@
#include "base/files/file_path.h"
#include "content/common/content_export.h"
+#include "webkit/browser/fileapi/file_system_url.h"
namespace content {
-// Helper method that returns whether or not the child process is allowed to
+// Helper function that returns whether or not the child process is allowed to
// open the specified |file| with the specified |pp_open_flags|.
CONTENT_EXPORT bool CanOpenWithPepperFlags(int pp_open_flags,
int child_id,
const base::FilePath& file);
+// Helper function that returns whether or not the child process is allowed to
+// open the specified file system |url| with the specified |pp_open_flags|.
+CONTENT_EXPORT bool CanOpenFileSystemURLWithPepperFlags(
+ int pp_open_flags,
+ int child_id,
+ const fileapi::FileSystemURL& url);
+
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_SECURITY_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
index 9dc585e3315..2f109cddb71 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -8,13 +8,16 @@
#include <vector>
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/content_client.h"
+#include "net/cert/x509_certificate.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
namespace content {
namespace pepper_socket_utils {
@@ -34,7 +37,7 @@ SocketPermissionRequest CreateSocketPermissionRequest(
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
int render_process_id,
int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -48,7 +51,7 @@ bool CanUseSocketAPIs(bool external_plugin,
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
RenderViewHost* render_view_host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -77,5 +80,60 @@ bool CanUseSocketAPIs(bool external_plugin,
return true;
}
+bool GetCertificateFields(const net::X509Certificate& cert,
+ ppapi::PPB_X509Certificate_Fields* fields) {
+ const net::CertPrincipal& issuer = cert.issuer();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
+ new base::StringValue(issuer.common_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
+ new base::StringValue(issuer.locality_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
+ new base::StringValue(issuer.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
+ new base::StringValue(issuer.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
+ new base::StringValue(JoinString(issuer.organization_names, '\n')));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
+ new base::StringValue(JoinString(issuer.organization_unit_names, '\n')));
+
+ const net::CertPrincipal& subject = cert.subject();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
+ new base::StringValue(subject.common_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
+ new base::StringValue(subject.locality_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
+ new base::StringValue(subject.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
+ new base::StringValue(subject.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
+ new base::StringValue(JoinString(subject.organization_names, '\n')));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
+ new base::StringValue(JoinString(subject.organization_unit_names, '\n')));
+
+ const std::string& serial_number = cert.serial_number();
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
+ base::BinaryValue::CreateWithCopiedBuffer(serial_number.data(),
+ serial_number.length()));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
+ new base::FundamentalValue(cert.valid_start().ToDoubleT()));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
+ new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
+ std::string der;
+ net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_RAW,
+ base::BinaryValue::CreateWithCopiedBuffer(der.data(), der.length()));
+ return true;
+}
+
+bool GetCertificateFields(const char* der,
+ uint32_t length,
+ ppapi::PPB_X509Certificate_Fields* fields) {
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromBytes(der, length);
+ if (!cert.get())
+ return false;
+ return GetCertificateFields(*cert.get(), fields);
+}
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
index 7a0cef56a5c..1a1a26cac19 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.h
@@ -6,9 +6,18 @@
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_SOCKET_UTILS_H_
#include "content/public/common/socket_permission_request.h"
+#include "ppapi/c/pp_stdint.h"
struct PP_NetAddress_Private;
+namespace net {
+class X509Certificate;
+}
+
+namespace ppapi {
+class PPB_X509Certificate_Fields;
+}
+
namespace content {
class RenderViewHost;
@@ -19,18 +28,32 @@ SocketPermissionRequest CreateSocketPermissionRequest(
SocketPermissionRequest::OperationType type,
const PP_NetAddress_Private& net_addr);
+// Returns true if the socket operation specified by |params| is allowed.
+// If |params| is NULL, this method checks the basic "socket" permission, which
+// is for those operations that don't require a specific socket permission rule.
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
int render_process_id,
int render_view_id);
// TODO (ygorshenin@): remove this method.
bool CanUseSocketAPIs(bool external_plugin,
bool private_api,
- const SocketPermissionRequest& params,
+ const SocketPermissionRequest* params,
RenderViewHost* render_view_host);
+// Extracts the certificate field data from a net::X509Certificate into
+// PPB_X509Certificate_Fields.
+bool GetCertificateFields(const net::X509Certificate& cert,
+ ppapi::PPB_X509Certificate_Fields* fields);
+
+// Extracts the certificate field data from the DER representation of a
+// certificate into PPB_X509Certificate_Fields.
+bool GetCertificateFields(const char* der,
+ uint32_t length,
+ ppapi::PPB_X509Certificate_Fields* fields);
+
} // namespace pepper_socket_utils
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index 48c8291cab9..063c11ed784 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -8,20 +8,22 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket/tcp_server_socket.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
using ppapi::NetAddressPrivateImpl;
@@ -36,18 +38,21 @@ size_t g_num_instances = 0;
namespace content {
PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
- bool private_api,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
- : state_(STATE_BEFORE_LISTENING),
- pepper_message_filter_(pepper_message_filter),
+ bool private_api)
+ : ppapi_host_(host->GetPpapiHost()),
+ factory_(factory),
+ instance_(instance),
+ state_(STATE_BEFORE_LISTENING),
external_plugin_(host->external_plugin()),
private_api_(private_api),
render_process_id_(0),
render_view_id_(0) {
++g_num_instances;
- DCHECK(host);
+ DCHECK(factory_);
+ DCHECK(ppapi_host_);
if (!host->GetRenderViewIDsForInstance(instance,
&render_process_id_,
&render_view_id_)) {
@@ -83,7 +88,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived(
IPC_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_TCPServerSocket_Listen, OnMsgListen)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_TCPServerSocket_Accept, OnMsgAccept)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening)
@@ -103,7 +108,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
content::SocketPermissionRequest::TCP_LISTEN, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
private_api_,
- request,
+ &request,
render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
@@ -117,8 +122,7 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
}
int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
- const ppapi::host::HostMessageContext* context,
- uint32 plugin_dispatcher_id) {
+ const ppapi::host::HostMessageContext* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(context);
@@ -129,12 +133,12 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
int net_result = socket_->Accept(
- &socket_buffer_,
+ &accepted_socket_,
+ &accepted_address_,
base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this),
- reply_context, plugin_dispatcher_id));
+ base::Unretained(this), reply_context));
if (net_result != net::ERR_IO_PENDING)
- OnAcceptCompleted(reply_context, plugin_dispatcher_id, net_result);
+ OnAcceptCompleted(reply_context, net_result);
return PP_OK_COMPLETIONPENDING;
}
@@ -165,8 +169,22 @@ void PepperTCPServerSocketMessageFilter::DoListen(
state_ = STATE_LISTEN_IN_PROGRESS;
- socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source()));
- int net_result = socket_->Listen(net::IPEndPoint(address, port), backlog);
+ socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
+ int net_result = net::OK;
+ do {
+ net::IPEndPoint ip_end_point(address, port);
+ net_result = socket_->Open(ip_end_point.GetFamily());
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->SetDefaultOptionsForServer();
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->Bind(ip_end_point);
+ if (net_result != net::OK)
+ break;
+ net_result = socket_->Listen(backlog);
+ } while (false);
+
if (net_result != net::ERR_IO_PENDING)
OnListenCompleted(context, net_result);
}
@@ -211,7 +229,6 @@ void PepperTCPServerSocketMessageFilter::OnListenCompleted(
void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
const ppapi::host::ReplyMessageContext& context,
- uint32 plugin_dispatcher_id,
int net_result) {
if (state_ != STATE_ACCEPT_IN_PROGRESS) {
SendAcceptError(context, PP_ERROR_FAILED);
@@ -226,16 +243,15 @@ void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
return;
}
- DCHECK(socket_buffer_.get());
+ DCHECK(accepted_socket_.get());
- scoped_ptr<net::StreamSocket> socket(socket_buffer_.release());
net::IPEndPoint ip_end_point_local;
- net::IPEndPoint ip_end_point_remote;
PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
int32_t pp_result =
- NetErrorToPepperError(socket->GetLocalAddress(&ip_end_point_local));
+ NetErrorToPepperError(accepted_socket_->GetLocalAddress(
+ &ip_end_point_local));
if (pp_result != PP_OK) {
SendAcceptError(context, pp_result);
return;
@@ -243,33 +259,27 @@ void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
ip_end_point_local.address(),
ip_end_point_local.port(),
- &local_addr)) {
- SendAcceptError(context, PP_ERROR_FAILED);
- return;
- }
- pp_result =
- NetErrorToPepperError(socket->GetPeerAddress(&ip_end_point_remote));
- if (pp_result != PP_OK) {
- SendAcceptError(context, pp_result);
- return;
- }
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_remote.address(),
- ip_end_point_remote.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ accepted_address_.address(),
+ accepted_address_.port(),
&remote_addr)) {
SendAcceptError(context, PP_ERROR_FAILED);
return;
}
- if (!pepper_message_filter_.get() || plugin_dispatcher_id == 0) {
- SendAcceptError(context, PP_ERROR_FAILED);
+
+ scoped_ptr<ppapi::host::ResourceHost> host =
+ factory_->CreateAcceptedTCPSocket(
+ instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE,
+ accepted_socket_.Pass());
+ if (!host) {
+ SendAcceptError(context, PP_ERROR_NOSPACE);
return;
}
- uint32 accepted_socket_id = pepper_message_filter_->AddAcceptedTCPSocket(
- ppapi::API_ID_PPB_TCPSOCKET_PRIVATE,
- plugin_dispatcher_id,
- socket.release());
- if (accepted_socket_id != 0) {
- SendAcceptReply(context, PP_OK, accepted_socket_id, local_addr,
+ int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass());
+ if (pending_resource_id) {
+ SendAcceptReply(context, PP_OK, pending_resource_id,
+ local_addr,
remote_addr);
} else {
SendAcceptError(context, PP_ERROR_NOSPACE);
@@ -296,13 +306,13 @@ void PepperTCPServerSocketMessageFilter::SendListenError(
void PepperTCPServerSocketMessageFilter::SendAcceptReply(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
- uint32 accepted_socket_id,
+ int pending_resource_id,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr) {
ppapi::host::ReplyMessageContext reply_context(context);
reply_context.params.set_result(pp_result);
SendReply(reply_context, PpapiPluginMsg_TCPServerSocket_AcceptReply(
- accepted_socket_id, local_addr, remote_addr));
+ pending_resource_id, local_addr, remote_addr));
}
void PepperTCPServerSocketMessageFilter::SendAcceptError(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
index ad8cf19f287..5d17333c9e8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
@@ -9,30 +9,35 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/common/content_export.h"
+#include "net/base/ip_endpoint.h"
+#include "net/socket/tcp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/host/resource_message_filter.h"
struct PP_NetAddress_Private;
-namespace net {
-class ServerSocket;
-class StreamSocket;
+namespace ppapi {
+namespace host {
+class PpapiHost;
+}
}
namespace content {
class BrowserPpapiHostImpl;
+class ContentBrowserPepperHostFactory;
+// TODO(yzshen): Remove this class entirely and let
+// TCPServerSocketPrivateResource inherit TCPSocketResourceBase.
class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
: public ppapi::host::ResourceMessageFilter {
public:
PepperTCPServerSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
- bool private_api,
- const scoped_refptr<PepperMessageFilter>& pepper_message_filter);
+ bool private_api);
static size_t GetNumInstances();
@@ -58,8 +63,7 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int32_t OnMsgListen(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& addr,
int32_t backlog);
- int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context,
- uint32 plugin_dispatcher_id);
+ int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context);
int32_t OnMsgStopListening(const ppapi::host::HostMessageContext* context);
void DoListen(const ppapi::host::ReplyMessageContext& context,
@@ -69,7 +73,6 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
void OnListenCompleted(const ppapi::host::ReplyMessageContext& context,
int net_result);
void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
- uint32 plugin_dispatcher_id,
int net_result);
void SendListenReply(const ppapi::host::ReplyMessageContext& context,
@@ -79,17 +82,23 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int32_t pp_result);
void SendAcceptReply(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
- uint32 accepted_socket_id,
+ int pending_resource_id,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr);
void SendAcceptError(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result);
// Following fields are initialized and used only on the IO thread.
+ // Non-owning ptr.
+ ppapi::host::PpapiHost* ppapi_host_;
+ // Non-owning ptr.
+ ContentBrowserPepperHostFactory* factory_;
+ PP_Instance instance_;
+
State state_;
- scoped_ptr<net::ServerSocket> socket_;
- scoped_ptr<net::StreamSocket> socket_buffer_;
- scoped_refptr<PepperMessageFilter> pepper_message_filter_;
+ scoped_ptr<net::TCPSocket> socket_;
+ scoped_ptr<net::TCPSocket> accepted_socket_;
+ net::IPEndPoint accepted_address_;
// Following fields are initialized on the IO thread but used only
// on the UI thread.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
index f05be8783ed..c5b752aa7f5 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
@@ -87,10 +87,12 @@ void PepperTCPSocket::Connect(const std::string& host, uint16_t port) {
connection_state_ = CONNECT_IN_PROGRESS;
net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
- resolver_.reset(new net::SingleRequestHostResolver(
- manager_->GetHostResolver()));
+ resolver_.reset(
+ new net::SingleRequestHostResolver(manager_->GetHostResolver()));
int net_result = resolver_->Resolve(
- request_info, &address_list_,
+ request_info,
+ net::DEFAULT_PRIORITY,
+ &address_list_,
base::Bind(&PepperTCPSocket::OnResolveCompleted, base::Unretained(this)),
net::BoundNetLog());
if (net_result != net::ERR_IO_PENDING)
@@ -141,16 +143,16 @@ void PepperTCPSocket::SSLHandshake(
connection_state_ = SSL_HANDSHAKE_IN_PROGRESS;
// TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
- net::ClientSocketHandle* handle = new net::ClientSocketHandle();
- handle->set_socket(socket_.release());
+ scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
+ handle->SetSocket(socket_.Pass());
net::ClientSocketFactory* factory =
net::ClientSocketFactory::GetDefaultFactory();
net::HostPortPair host_port_pair(server_name, server_port);
net::SSLClientSocketContext ssl_context;
ssl_context.cert_verifier = manager_->GetCertVerifier();
ssl_context.transport_security_state = manager_->GetTransportSecurityState();
- socket_.reset(factory->CreateSSLClientSocket(
- handle, host_port_pair, manager_->ssl_config(), ssl_context));
+ socket_ = factory->CreateSSLClientSocket(
+ handle.Pass(), host_port_pair, manager_->ssl_config(), ssl_context);
if (!socket_) {
LOG(WARNING) << "Failed to create an SSL client socket.";
OnSSLHandshakeCompleted(net::ERR_UNEXPECTED);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h
deleted file mode 100644
index 986afb015bb..00000000000
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
-#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/ppb_tcp_socket.h"
-
-struct PP_NetAddress_Private;
-
-namespace ppapi {
-class PPB_X509Certificate_Fields;
-class SocketOptionData;
-}
-
-namespace net {
-class DrainableIOBuffer;
-class IOBuffer;
-class SingleRequestHostResolver;
-class StreamSocket;
-class X509Certificate;
-}
-
-namespace content {
-class PepperMessageFilter;
-
-// PepperTCPSocket is used by PepperMessageFilter to handle requests from
-// the Pepper TCP socket API (PPB_TCPSocket and PPB_TCPSocket_Private).
-class PepperTCPSocket {
- public:
- PepperTCPSocket(PepperMessageFilter* manager,
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32 socket_id,
- bool private_api);
-
- // Used for creation already connected sockets. Takes ownership of
- // |socket|.
- PepperTCPSocket(PepperMessageFilter* manager,
- int32 routing_id,
- uint32 plugin_dispatcher_id,
- uint32 socket_id,
- net::StreamSocket* socket,
- bool private_api);
- ~PepperTCPSocket();
-
- int routing_id() { return routing_id_; }
- bool private_api() const { return private_api_; }
-
- void Connect(const std::string& host, uint16_t port);
- void ConnectWithNetAddress(const PP_NetAddress_Private& net_addr);
- void SSLHandshake(
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs);
- void Read(int32 bytes_to_read);
- void Write(const std::string& data);
- void SetOption(PP_TCPSocket_Option name,
- const ppapi::SocketOptionData& value);
-
- void SendConnectACKError(int32_t error);
-
- // Extracts the certificate field data from a |net::X509Certificate| into
- // |PPB_X509Certificate_Fields|.
- static bool GetCertificateFields(const net::X509Certificate& cert,
- ppapi::PPB_X509Certificate_Fields* fields);
- // Extracts the certificate field data from the DER representation of a
- // certificate into |PPB_X509Certificate_Fields|.
- static bool GetCertificateFields(const char* der,
- uint32_t length,
- ppapi::PPB_X509Certificate_Fields* fields);
-
- private:
- enum ConnectionState {
- // Before a connection is successfully established (including a previous
- // connect request failed).
- BEFORE_CONNECT,
- // There is a connect request that is pending.
- CONNECT_IN_PROGRESS,
- // A connection has been successfully established.
- CONNECTED,
- // There is an SSL handshake request that is pending.
- SSL_HANDSHAKE_IN_PROGRESS,
- // An SSL connection has been successfully established.
- SSL_CONNECTED,
- // An SSL handshake has failed.
- SSL_HANDSHAKE_FAILED
- };
-
- void StartConnect(const net::AddressList& addresses);
-
- void SendReadACKError(int32_t error);
- void SendWriteACKError(int32_t error);
- void SendSSLHandshakeACK(bool succeeded);
- void SendSetOptionACK(int32_t result);
-
- void OnResolveCompleted(int net_result);
- void OnConnectCompleted(int net_result);
- void OnSSLHandshakeCompleted(int net_result);
- void OnReadCompleted(int net_result);
- void OnWriteCompleted(int net_result);
-
- bool IsConnected() const;
- bool IsSsl() const;
-
- // Actually does a write from |write_buffer_|; possibly called many times for
- // each |Write()|.
- void DoWrite();
-
- PepperMessageFilter* manager_;
- int32 routing_id_;
- uint32 plugin_dispatcher_id_;
- uint32 socket_id_;
- bool private_api_;
-
- ConnectionState connection_state_;
- bool end_of_file_reached_;
-
- scoped_ptr<net::SingleRequestHostResolver> resolver_;
- net::AddressList address_list_;
-
- scoped_ptr<net::StreamSocket> socket_;
-
- scoped_refptr<net::IOBuffer> read_buffer_;
-
- // |StreamSocket::Write()| may not always write the full buffer, but we would
- // rather have our |Write()| do so whenever possible. To do this, we may have
- // to call the former multiple times for each of the latter. This entails
- // using a |DrainableIOBuffer|, which requires an underlying base |IOBuffer|.
- scoped_refptr<net::IOBuffer> write_buffer_base_;
- scoped_refptr<net::DrainableIOBuffer> write_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTCPSocket);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
new file mode 100644
index 00000000000..f943f39eb9e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -0,0 +1,979 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
+
+#include <cstring>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
+#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/socket_permission_request.h"
+#include "net/base/address_family.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/dns/single_request_host_resolver.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/tcp_client_socket.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/error_conversion.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/tcp_socket_resource_base.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+
+using ppapi::NetAddressPrivateImpl;
+using ppapi::host::NetErrorToPepperError;
+using ppapi::proxy::TCPSocketResourceBase;
+using ppapi::TCPSocketState;
+using ppapi::TCPSocketVersion;
+
+namespace {
+
+size_t g_num_instances = 0;
+
+} // namespace
+
+namespace content {
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ TCPSocketVersion version)
+ : version_(version),
+ external_plugin_(host->external_plugin()),
+ render_process_id_(0),
+ render_view_id_(0),
+ ppapi_host_(host->GetPpapiHost()),
+ factory_(factory),
+ instance_(instance),
+ state_(TCPSocketState::INITIAL),
+ end_of_file_reached_(false),
+ bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
+ address_index_(0),
+ socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
+ ssl_context_helper_(host->ssl_context_helper()),
+ pending_accept_(false) {
+ DCHECK(host);
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket)
+ : version_(version),
+ external_plugin_(host->external_plugin()),
+ render_process_id_(0),
+ render_view_id_(0),
+ ppapi_host_(host->GetPpapiHost()),
+ factory_(NULL),
+ instance_(instance),
+ state_(TCPSocketState::CONNECTED),
+ end_of_file_reached_(false),
+ bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
+ address_index_(0),
+ socket_(socket.Pass()),
+ ssl_context_helper_(host->ssl_context_helper()),
+ pending_accept_(false) {
+ DCHECK(host);
+ DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
+
+ ++g_num_instances;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &render_view_id_)) {
+ NOTREACHED();
+ }
+}
+
+PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
+ if (socket_)
+ socket_->Close();
+ if (ssl_socket_)
+ ssl_socket_->Disconnect();
+ --g_num_instances;
+}
+
+// static
+size_t PepperTCPSocketMessageFilter::GetNumInstances() {
+ return g_num_instances;
+}
+
+scoped_refptr<base::TaskRunner>
+PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
+ switch (message.type()) {
+ case PpapiHostMsg_TCPSocket_Bind::ID:
+ case PpapiHostMsg_TCPSocket_Connect::ID:
+ case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
+ case PpapiHostMsg_TCPSocket_Listen::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+ case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
+ case PpapiHostMsg_TCPSocket_Read::ID:
+ case PpapiHostMsg_TCPSocket_Write::ID:
+ case PpapiHostMsg_TCPSocket_Accept::ID:
+ case PpapiHostMsg_TCPSocket_Close::ID:
+ case PpapiHostMsg_TCPSocket_SetOption::ID:
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ }
+ return NULL;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Connect, OnMsgConnect)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
+ OnMsgConnectWithNetAddress)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Read, OnMsgRead)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_Listen, OnMsgListen)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TCPSocket_Accept, OnMsgAccept)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_TCPSocket_Close, OnMsgClose)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgBind(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket v1.1 or above.
+ if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, false /* private_api */, NULL, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ bind_input_addr_ = net_addr;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoBind, this,
+ context->MakeReplyMessageContext(), net_addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& host,
+ uint16_t port) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket_Private.
+ if (!IsPrivateAPI()) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
+ host,
+ port);
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, true /* private_api */, &request,
+ render_process_id_, render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!render_process_host)
+ return PP_ERROR_FAILED;
+ BrowserContext* browser_context = render_process_host->GetBrowserContext();
+ if (!browser_context || !browser_context->GetResourceContext())
+ return PP_ERROR_FAILED;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this,
+ context->MakeReplyMessageContext(),
+ host, port, browser_context->GetResourceContext()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ content::SocketPermissionRequest request =
+ pepper_socket_utils::CreateSocketPermissionRequest(
+ content::SocketPermissionRequest::TCP_CONNECT, net_addr);
+ if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
+ &request, render_process_id_,
+ render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
+ context->MakeReplyMessageContext(), net_addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Allow to do SSL handshake only if currently the socket has been connected
+ // and there isn't pending read or write.
+ if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
+ read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
+ return PP_ERROR_FAILED;
+ }
+
+ // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
+ net::IPEndPoint peer_address;
+ if (socket_->GetPeerAddress(&peer_address) != net::OK)
+ return PP_ERROR_FAILED;
+
+ scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
+ handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
+ new net::TCPClientSocket(socket_.Pass(), peer_address)));
+ net::ClientSocketFactory* factory =
+ net::ClientSocketFactory::GetDefaultFactory();
+ net::HostPortPair host_port_pair(server_name, server_port);
+ net::SSLClientSocketContext ssl_context;
+ ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
+ ssl_context.transport_security_state =
+ ssl_context_helper_->GetTransportSecurityState();
+ ssl_socket_ = factory->CreateSSLClientSocket(
+ handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(),
+ ssl_context);
+ if (!ssl_socket_) {
+ LOG(WARNING) << "Failed to create an SSL client socket.";
+ state_.CompletePendingTransition(false);
+ return PP_ERROR_FAILED;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
+
+ const ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ int net_result = ssl_socket_->Connect(
+ base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnSSLHandshakeCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgRead(
+ const ppapi::host::HostMessageContext* context,
+ int32_t bytes_to_read) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!state_.IsConnected() || end_of_file_reached_)
+ return PP_ERROR_FAILED;
+ if (read_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+ if (bytes_to_read <= 0 ||
+ bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ read_buffer_ = new net::IOBuffer(bytes_to_read);
+
+ int net_result = net::ERR_FAILED;
+ if (socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
+ net_result = socket_->Read(
+ read_buffer_.get(),
+ bytes_to_read,
+ base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
+ } else if (ssl_socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
+ net_result = ssl_socket_->Read(
+ read_buffer_.get(),
+ bytes_to_read,
+ base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
+ base::Unretained(this), reply_context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnReadCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& data) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsConnected())
+ return PP_ERROR_FAILED;
+ if (write_buffer_base_.get() || write_buffer_.get())
+ return PP_ERROR_INPROGRESS;
+
+ size_t data_size = data.size();
+ if (data_size == 0 ||
+ data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ write_buffer_base_ = new net::IOBuffer(data_size);
+ memcpy(write_buffer_base_->data(), data.data(), data_size);
+ write_buffer_ =
+ new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
+ DoWrite(context->MakeReplyMessageContext());
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgListen(
+ const ppapi::host::HostMessageContext* context,
+ int32_t backlog) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // This is only supported by PPB_TCPSocket v1.1 or above.
+ if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ NOTREACHED();
+ return PP_ERROR_NOACCESS;
+ }
+
+ content::SocketPermissionRequest request =
+ pepper_socket_utils::CreateSocketPermissionRequest(
+ content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, false /* private_api */, &request,
+ render_process_id_, render_view_id_)) {
+ return PP_ERROR_NOACCESS;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PepperTCPSocketMessageFilter::DoListen, this,
+ context->MakeReplyMessageContext(), backlog));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (pending_accept_)
+ return PP_ERROR_INPROGRESS;
+ if (state_.state() != TCPSocketState::LISTENING)
+ return PP_ERROR_FAILED;
+
+ pending_accept_ = true;
+ ppapi::host::ReplyMessageContext reply_context(
+ context->MakeReplyMessageContext());
+ int net_result = socket_->Accept(
+ &accepted_socket_,
+ &accepted_address_,
+ base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
+ base::Unretained(this), reply_context));
+ if (net_result != net::ERR_IO_PENDING)
+ OnAcceptCompleted(reply_context, net_result);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgClose(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (state_.state() == TCPSocketState::CLOSED)
+ return PP_OK;
+
+ state_.DoTransition(TCPSocketState::CLOSE, true);
+ // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
+ if (socket_) {
+ socket_->Close();
+ } else if (ssl_socket_) {
+ ssl_socket_->Disconnect();
+ }
+ return PP_OK;
+}
+
+int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
+ const ppapi::host::HostMessageContext* context,
+ PP_TCPSocket_Option name,
+ const ppapi::SocketOptionData& value) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ switch (name) {
+ case PP_TCPSOCKET_OPTION_NO_DELAY: {
+ if (state_.state() != TCPSocketState::CONNECTED)
+ return PP_ERROR_FAILED;
+
+ bool boolean_value = false;
+ if (!value.GetBool(&boolean_value))
+ return PP_ERROR_BADARGUMENT;
+ return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
+ }
+ case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
+ case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
+ if (state_.state() != TCPSocketState::CONNECTED)
+ return PP_ERROR_FAILED;
+
+ int32_t integer_value = 0;
+ if (!value.GetInt32(&integer_value) || integer_value <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ bool result = false;
+ if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
+ if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = socket_->SetSendBufferSize(integer_value);
+ } else {
+ if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
+ return PP_ERROR_BADARGUMENT;
+ result = socket_->SetReceiveBufferSize(integer_value);
+ }
+ return result ? PP_OK : PP_ERROR_FAILED;
+ }
+ default: {
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+ }
+}
+
+void PepperTCPSocketMessageFilter::DoBind(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_.IsPending(TCPSocketState::BIND)) {
+ SendBindError(context, PP_ERROR_INPROGRESS);
+ return;
+ }
+ if (!state_.IsValidTransition(TCPSocketState::BIND)) {
+ SendBindError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int pp_result = PP_OK;
+ do {
+ net::IPAddressNumber address;
+ int port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+ net::IPEndPoint bind_addr(address, port);
+
+ DCHECK(!socket_->IsValid());
+ pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
+ if (pp_result != PP_OK)
+ break;
+
+ pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
+ if (pp_result != PP_OK)
+ break;
+
+ pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
+ if (pp_result != PP_OK)
+ break;
+
+ net::IPEndPoint ip_end_point_local;
+ pp_result = NetErrorToPepperError(
+ socket_->GetLocalAddress(&ip_end_point_local));
+ if (pp_result != PP_OK)
+ break;
+
+ PP_NetAddress_Private local_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+
+ SendBindReply(context, PP_OK, local_addr);
+ state_.DoTransition(TCPSocketState::BIND, true);
+ return;
+ } while (false);
+ if (socket_->IsValid())
+ socket_->Close();
+ SendBindError(context, pp_result);
+ state_.DoTransition(TCPSocketState::BIND, false);
+}
+
+void PepperTCPSocketMessageFilter::DoConnect(
+ const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ ResourceContext* resource_context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+ address_index_ = 0;
+ address_list_.clear();
+ net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
+ resolver_.reset(new net::SingleRequestHostResolver(
+ resource_context->GetHostResolver()));
+ int net_result = resolver_->Resolve(
+ request_info,
+ net::DEFAULT_PRIORITY,
+ &address_list_,
+ base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
+ base::Unretained(this), context),
+ net::BoundNetLog());
+ if (net_result != net::ERR_IO_PENDING)
+ OnResolveCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+
+ net::IPAddressNumber address;
+ int port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ state_.CompletePendingTransition(false);
+ SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
+ return;
+ }
+
+ // Copy the single IPEndPoint to address_list_.
+ address_index_ = 0;
+ address_list_.clear();
+ address_list_.push_back(net::IPEndPoint(address, port));
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::DoWrite(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+ DCHECK_GT(write_buffer_->BytesRemaining(), 0);
+ DCHECK(state_.IsConnected());
+
+ int net_result = net::ERR_FAILED;
+ if (socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
+ net_result = socket_->Write(
+ write_buffer_.get(),
+ write_buffer_->BytesRemaining(),
+ base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context));
+ } else if (ssl_socket_) {
+ DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
+ net_result = ssl_socket_->Write(
+ write_buffer_.get(),
+ write_buffer_->BytesRemaining(),
+ base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
+ base::Unretained(this), context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnWriteCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::DoListen(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t backlog) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_.IsPending(TCPSocketState::LISTEN)) {
+ SendListenReply(context, PP_ERROR_INPROGRESS);
+ return;
+ }
+ if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
+ SendListenReply(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
+ SendListenReply(context, pp_result);
+ state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
+}
+
+void PepperTCPSocketMessageFilter::OnResolveCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ if (net_result != net::OK) {
+ SendConnectError(context, NetErrorToPepperError(net_result));
+ state_.CompletePendingTransition(false);
+ return;
+ }
+
+ StartConnect(context);
+}
+
+void PepperTCPSocketMessageFilter::StartConnect(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(state_.IsPending(TCPSocketState::CONNECT));
+ DCHECK_LT(address_index_, address_list_.size());
+
+ int net_result = net::OK;
+ if (!socket_->IsValid())
+ net_result = socket_->Open(address_list_[address_index_].GetFamily());
+
+ if (net_result == net::OK) {
+ net_result = socket_->Connect(
+ address_list_[address_index_],
+ base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
+ base::Unretained(this), context));
+ }
+ if (net_result != net::ERR_IO_PENDING)
+ OnConnectCompleted(context, net_result);
+}
+
+void PepperTCPSocketMessageFilter::OnConnectCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ int32_t pp_result = NetErrorToPepperError(net_result);
+ do {
+ if (pp_result != PP_OK)
+ break;
+
+ net::IPEndPoint ip_end_point_local;
+ net::IPEndPoint ip_end_point_remote;
+ pp_result = NetErrorToPepperError(
+ socket_->GetLocalAddress(&ip_end_point_local));
+ if (pp_result != PP_OK)
+ break;
+ pp_result = NetErrorToPepperError(
+ socket_->GetPeerAddress(&ip_end_point_remote));
+ if (pp_result != PP_OK)
+ break;
+
+ PP_NetAddress_Private local_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ PP_NetAddress_Private remote_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_remote.address(),
+ ip_end_point_remote.port(),
+ &remote_addr)) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ break;
+ }
+
+ socket_->SetDefaultOptionsForClient();
+ SendConnectReply(context, PP_OK, local_addr, remote_addr);
+ state_.CompletePendingTransition(true);
+ return;
+ } while (false);
+
+ if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ DCHECK_EQ(1u, address_list_.size());
+
+ SendConnectError(context, pp_result);
+ state_.CompletePendingTransition(false);
+ } else {
+ // We have to recreate |socket_| because it doesn't allow a second connect
+ // attempt. We won't lose any state such as bound address or set options,
+ // because in the private or v1.0 API, connect must be the first operation.
+ socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
+
+ if (address_index_ + 1 < address_list_.size()) {
+ DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
+ address_index_++;
+ StartConnect(context);
+ } else {
+ SendConnectError(context, pp_result);
+ // In order to maintain backward compatibility, allow further attempts to
+ // connect the socket.
+ state_ = TCPSocketState(TCPSocketState::INITIAL);
+ }
+ }
+}
+
+void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendSSLHandshakeReply(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
+ state_.CompletePendingTransition(net_result == net::OK);
+}
+
+void PepperTCPSocketMessageFilter::OnReadCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(read_buffer_.get());
+
+ if (net_result > 0) {
+ SendReadReply(context,
+ PP_OK,
+ std::string(read_buffer_->data(), net_result));
+ } else if (net_result == 0) {
+ end_of_file_reached_ = true;
+ SendReadReply(context, PP_OK, std::string());
+ } else {
+ SendReadError(context, NetErrorToPepperError(net_result));
+ }
+ read_buffer_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::OnWriteCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(write_buffer_base_.get());
+ DCHECK(write_buffer_.get());
+
+ // Note: For partial writes of 0 bytes, don't continue writing to avoid a
+ // likely infinite loop.
+ if (net_result > 0) {
+ write_buffer_->DidConsume(net_result);
+ if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
+ DoWrite(context);
+ return;
+ }
+ }
+
+ if (net_result >= 0)
+ SendWriteReply(context, write_buffer_->BytesConsumed());
+ else
+ SendWriteReply(context, NetErrorToPepperError(net_result));
+
+ write_buffer_ = NULL;
+ write_buffer_base_ = NULL;
+}
+
+void PepperTCPSocketMessageFilter::OnAcceptCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(pending_accept_);
+
+ pending_accept_ = false;
+
+ if (net_result != net::OK) {
+ SendAcceptError(context, NetErrorToPepperError(net_result));
+ return;
+ }
+
+ DCHECK(accepted_socket_.get());
+
+ net::IPEndPoint ip_end_point_local;
+ PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
+ PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
+
+ int32_t pp_result =
+ NetErrorToPepperError(accepted_socket_->GetLocalAddress(
+ &ip_end_point_local));
+ if (pp_result != PP_OK) {
+ SendAcceptError(context, pp_result);
+ return;
+ }
+ if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
+ ip_end_point_local.address(),
+ ip_end_point_local.port(),
+ &local_addr) ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ accepted_address_.address(),
+ accepted_address_.port(),
+ &remote_addr)) {
+ SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
+ return;
+ }
+
+ // |factory_| is guaranteed to be non-NULL here. Only those instances created
+ // in CONNECTED state have a NULL |factory_|, while getting here requires
+ // LISTENING state.
+ scoped_ptr<ppapi::host::ResourceHost> host =
+ factory_->CreateAcceptedTCPSocket(
+ instance_, version_, accepted_socket_.Pass());
+ if (!host) {
+ SendAcceptError(context, PP_ERROR_NOSPACE);
+ return;
+ }
+ int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
+ if (pending_host_id)
+ SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
+ else
+ SendAcceptError(context, PP_ERROR_NOSPACE);
+}
+
+void PepperTCPSocketMessageFilter::SendBindReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendBindError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+void PepperTCPSocketMessageFilter::SendConnectReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendConnectError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendConnectReply(context,
+ pp_error,
+ NetAddressPrivateImpl::kInvalidNetAddress,
+ NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ ppapi::PPB_X509Certificate_Fields certificate_fields;
+ if (pp_result == PP_OK) {
+ // Our socket is guaranteed to be an SSL socket if we get here.
+ net::SSLInfo ssl_info;
+ ssl_socket_->GetSSLInfo(&ssl_info);
+ if (ssl_info.cert.get()) {
+ pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
+ &certificate_fields);
+ }
+ }
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
+}
+
+void PepperTCPSocketMessageFilter::SendReadReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const std::string& data) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
+}
+
+void PepperTCPSocketMessageFilter::SendReadError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendReadReply(context, pp_error, std::string());
+}
+
+void PepperTCPSocketMessageFilter::SendWriteReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
+}
+
+void PepperTCPSocketMessageFilter::SendListenReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
+}
+
+void PepperTCPSocketMessageFilter::SendAcceptReply(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ ppapi::host::ReplyMessageContext reply_context(context);
+ reply_context.params.set_result(pp_result);
+ SendReply(reply_context,
+ PpapiPluginMsg_TCPSocket_AcceptReply(
+ pending_host_id, local_addr, remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::SendAcceptError(
+ const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error) {
+ SendAcceptReply(context, pp_error, 0,
+ NetAddressPrivateImpl::kInvalidNetAddress,
+ NetAddressPrivateImpl::kInvalidNetAddress);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
new file mode 100644
index 00000000000..fb34b988d3c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -0,0 +1,223 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
+#include "content/common/content_export.h"
+#include "net/base/address_list.h"
+#include "net/base/ip_endpoint.h"
+#include "net/socket/tcp_socket.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppb_tcp_socket.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/host/resource_message_filter.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
+
+namespace net {
+enum AddressFamily;
+class DrainableIOBuffer;
+class IOBuffer;
+class SingleRequestHostResolver;
+class SSLClientSocket;
+}
+
+namespace ppapi {
+class SocketOptionData;
+
+namespace host {
+class PpapiHost;
+struct ReplyMessageContext;
+}
+}
+
+namespace content {
+
+class BrowserPpapiHostImpl;
+class ContentBrowserPepperHostFactory;
+class ResourceContext;
+
+class CONTENT_EXPORT PepperTCPSocketMessageFilter
+ : public ppapi::host::ResourceMessageFilter {
+ public:
+ PepperTCPSocketMessageFilter(
+ ContentBrowserPepperHostFactory* factory,
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version);
+
+ // Used for creating already connected sockets.
+ PepperTCPSocketMessageFilter(
+ BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ ppapi::TCPSocketVersion version,
+ scoped_ptr<net::TCPSocket> socket);
+
+ static size_t GetNumInstances();
+
+ private:
+ virtual ~PepperTCPSocketMessageFilter();
+
+ // ppapi::host::ResourceMessageFilter overrides.
+ virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) OVERRIDE;
+ virtual int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr);
+ int32_t OnMsgConnect(const ppapi::host::HostMessageContext* context,
+ const std::string& host,
+ uint16_t port);
+ int32_t OnMsgConnectWithNetAddress(
+ const ppapi::host::HostMessageContext* context,
+ const PP_NetAddress_Private& net_addr);
+ int32_t OnMsgSSLHandshake(
+ const ppapi::host::HostMessageContext* context,
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs);
+ int32_t OnMsgRead(const ppapi::host::HostMessageContext* context,
+ int32_t bytes_to_read);
+ int32_t OnMsgWrite(const ppapi::host::HostMessageContext* context,
+ const std::string& data);
+ int32_t OnMsgListen(const ppapi::host::HostMessageContext* context,
+ int32_t backlog);
+ int32_t OnMsgAccept(const ppapi::host::HostMessageContext* context);
+ int32_t OnMsgClose(const ppapi::host::HostMessageContext* context);
+ int32_t OnMsgSetOption(const ppapi::host::HostMessageContext* context,
+ PP_TCPSocket_Option name,
+ const ppapi::SocketOptionData& value);
+
+ void DoBind(const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr);
+ void DoConnect(const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ ResourceContext* resource_context);
+ void DoConnectWithNetAddress(
+ const ppapi::host::ReplyMessageContext& context,
+ const PP_NetAddress_Private& net_addr);
+ void DoWrite(const ppapi::host::ReplyMessageContext& context);
+ void DoListen(const ppapi::host::ReplyMessageContext& context,
+ int32_t backlog);
+
+ void OnResolveCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void StartConnect(const ppapi::host::ReplyMessageContext& context);
+
+ void OnConnectCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnSSLHandshakeCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnReadCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnWriteCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+ void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result);
+
+ void SendBindReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr);
+ void SendBindError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendConnectReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void SendConnectError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendSSLHandshakeReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendReadReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ const std::string& data);
+ void SendReadError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+ void SendWriteReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendListenReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result);
+ void SendAcceptReply(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_result,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void SendAcceptError(const ppapi::host::ReplyMessageContext& context,
+ int32_t pp_error);
+
+ bool IsPrivateAPI() const {
+ return version_ == ppapi::TCP_SOCKET_VERSION_PRIVATE;
+ }
+
+ // The following fields are used on both the UI and IO thread.
+ const ppapi::TCPSocketVersion version_;
+
+ // The following fields are used only on the UI thread.
+ const bool external_plugin_;
+
+ int render_process_id_;
+ int render_view_id_;
+
+ // The following fields are used only on the IO thread.
+ // Non-owning ptr.
+ ppapi::host::PpapiHost* ppapi_host_;
+ // Non-owning ptr.
+ ContentBrowserPepperHostFactory* factory_;
+ PP_Instance instance_;
+
+ ppapi::TCPSocketState state_;
+ bool end_of_file_reached_;
+
+ // This is the address requested to bind. Please note that this is not the
+ // bound address. For example, |bind_input_addr_| may have port set to 0.
+ // It is used to check permission for listening.
+ PP_NetAddress_Private bind_input_addr_;
+
+ scoped_ptr<net::SingleRequestHostResolver> resolver_;
+
+ // |address_list_| may store multiple addresses when
+ // PPB_TCPSocket_Private.Connect() is used, which involves name resolution.
+ // In that case, we will try each address in the list until a connection is
+ // successfully established.
+ net::AddressList address_list_;
+ // Where we are in the above list.
+ size_t address_index_;
+
+ // Non-null unless an SSL connection is requested.
+ scoped_ptr<net::TCPSocket> socket_;
+ // Non-null if an SSL connection is requested.
+ scoped_ptr<net::SSLClientSocket> ssl_socket_;
+
+ scoped_refptr<net::IOBuffer> read_buffer_;
+
+ // TCPSocket::Write() may not always write the full buffer, but we would
+ // rather have our DoWrite() do so whenever possible. To do this, we may have
+ // to call the former multiple times for each of the latter. This entails
+ // using a DrainableIOBuffer, which requires an underlying base IOBuffer.
+ scoped_refptr<net::IOBuffer> write_buffer_base_;
+ scoped_refptr<net::DrainableIOBuffer> write_buffer_;
+ scoped_refptr<SSLContextHelper> ssl_context_helper_;
+
+ bool pending_accept_;
+ scoped_ptr<net::TCPSocket> accepted_socket_;
+ net::IPEndPoint accepted_address_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTCPSocketMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TCP_SOCKET_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index 7453fd2886a..3127ed278fd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -28,8 +28,8 @@
#include "ppapi/shared_impl/private/net_address_private_impl.h"
#include "ppapi/shared_impl/socket_option_data.h"
-using ppapi::host::NetErrorToPepperError;
using ppapi::NetAddressPrivateImpl;
+using ppapi::host::NetErrorToPepperError;
namespace {
@@ -173,7 +173,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
pepper_socket_utils::CreateSocketPermissionRequest(
SocketPermissionRequest::UDP_BIND, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
- request, render_process_id_,
+ &request, render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
}
@@ -236,7 +236,7 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
pepper_socket_utils::CreateSocketPermissionRequest(
SocketPermissionRequest::UDP_SEND_TO, addr);
if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, private_api_,
- request, render_process_id_,
+ &request, render_process_id_,
render_view_id_)) {
return PP_ERROR_NOACCESS;
}
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
new file mode 100644
index 00000000000..3b92e6d0c16
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
+
+#include "net/cert/cert_verifier.h"
+#include "net/http/transport_security_state.h"
+
+namespace content {
+
+SSLContextHelper::SSLContextHelper() {
+}
+
+SSLContextHelper::~SSLContextHelper() {
+}
+
+net::CertVerifier* SSLContextHelper::GetCertVerifier() {
+ if (!cert_verifier_)
+ cert_verifier_.reset(net::CertVerifier::CreateDefault());
+ return cert_verifier_.get();
+}
+
+net::TransportSecurityState* SSLContextHelper::GetTransportSecurityState() {
+ if (!transport_security_state_)
+ transport_security_state_.reset(new net::TransportSecurityState());
+ return transport_security_state_.get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
new file mode 100644
index 00000000000..f1da2a6ee1d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/ssl/ssl_config_service.h"
+
+namespace net {
+class CertVerifier;
+class TransportSecurityState;
+}
+
+namespace content {
+
+class SSLContextHelper : public base::RefCounted<SSLContextHelper> {
+ public:
+ SSLContextHelper();
+
+ net::CertVerifier* GetCertVerifier();
+ net::TransportSecurityState* GetTransportSecurityState();
+ const net::SSLConfig& ssl_config() { return ssl_config_; }
+
+ private:
+ friend class base::RefCounted<SSLContextHelper>;
+
+ ~SSLContextHelper();
+
+ // This is lazily created. Users should use GetCertVerifier to retrieve it.
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+ // This is lazily created. Users should use GetTransportSecurityState to
+ // retrieve it.
+ scoped_ptr<net::TransportSecurityState> transport_security_state_;
+
+ // The default SSL configuration settings are used, as opposed to Chrome's SSL
+ // settings.
+ net::SSLConfig ssl_config_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLContextHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc
index ea511d0b8c3..ec621c10dca 100644
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4,31 +4,64 @@
#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
namespace content {
+// The (process id, routing id) pair that identifies one RenderFrame.
+typedef std::pair<int32, int32> RenderFrameHostID;
+typedef base::hash_map<RenderFrameHostID, RenderFrameHostImpl*>
+ RoutingIDFrameMap;
+static base::LazyInstance<RoutingIDFrameMap> g_routing_id_frame_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+RenderFrameHostImpl* RenderFrameHostImpl::FromID(
+ int process_id, int routing_id) {
+ RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
+ RoutingIDFrameMap::iterator it = frames->find(
+ RenderFrameHostID(process_id, routing_id));
+ return it == frames->end() ? NULL : it->second;
+}
+
RenderFrameHostImpl::RenderFrameHostImpl(
RenderViewHostImpl* render_view_host,
int routing_id,
- bool swapped_out)
+ bool is_swapped_out)
: render_view_host_(render_view_host),
- routing_id_(routing_id) {
+ routing_id_(routing_id),
+ is_swapped_out_(is_swapped_out) {
+ GetProcess()->AddRoute(routing_id_, this);
+ g_routing_id_frame_map.Get().insert(std::make_pair(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_),
+ this));
}
RenderFrameHostImpl::~RenderFrameHostImpl() {
+ GetProcess()->RemoveRoute(routing_id_);
+ g_routing_id_frame_map.Get().erase(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_));
+
}
bool RenderFrameHostImpl::Send(IPC::Message* message) {
- // Use the RenderViewHost object to send the message. It inherits it from
- // RenderWidgetHost, which ultimately uses the current process's |Send|.
- return render_view_host_->Send(message);
+ return GetProcess()->Send(message);
}
bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
- // Pass the message up to the RenderViewHost, until we have enough
- // infrastructure to start processing messages in this object.
- return render_view_host_->OnMessageReceived(msg);
+ return false;
+}
+
+void RenderFrameHostImpl::Init() {
+ GetProcess()->ResumeRequestsForView(routing_id());
+}
+
+RenderProcessHost* RenderFrameHostImpl::GetProcess() const {
+ // TODO(ajwong): This should return its own process once cross-process
+ // subframe navigations are supported.
+ return render_view_host_->GetProcess();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.h b/chromium/content/browser/renderer_host/render_frame_host_impl.h
index bb94c8e63c2..78df3331efd 100644
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_frame_host_impl.h
@@ -10,14 +10,16 @@
namespace content {
+class RenderProcessHost;
class RenderViewHostImpl;
class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
public:
- RenderFrameHostImpl(
- RenderViewHostImpl* render_view_host,
- int routing_id,
- bool swapped_out);
+ static RenderFrameHostImpl* FromID(int process_id, int routing_id);
+
+ RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
+ int routing_id,
+ bool is_swapped_out);
virtual ~RenderFrameHostImpl();
// IPC::Sender
@@ -26,12 +28,16 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- int routing_id() { return routing_id_; }
+ void Init();
+ RenderProcessHost* GetProcess() const;
+ int routing_id() const { return routing_id_; }
private:
- RenderViewHostImpl* render_view_host_;
+ bool is_swapped_out() { return is_swapped_out_; }
+ RenderViewHostImpl* render_view_host_; // Not owned. Outlives this object.
int routing_id_;
+ bool is_swapped_out_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImpl);
};
diff --git a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
index 9ee8036e044..de64924d717 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -8,7 +8,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_notification_tracker.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.cc b/chromium/content/browser/renderer_host/render_process_host_impl.cc
index 2dd784a4e69..73cb5e11f9c 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -52,6 +52,7 @@
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/fileapi/fileapi_message_filter.h"
#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_disk_cache.h"
@@ -60,6 +61,7 @@
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_scheduler_filter.h"
+#include "content/browser/media/android/browser_demuxer_android.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/mime_registry_message_filter.h"
#include "content/browser/plugin_service_impl.h"
@@ -91,6 +93,8 @@
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.h"
#include "content/browser/resolve_proxy_msg_helper.h"
+#include "content/browser/service_worker/service_worker_context.h"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
@@ -111,6 +115,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.h"
#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_constants.h"
@@ -118,8 +123,6 @@
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
-#include "content/renderer/render_process_impl.h"
-#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_logging.h"
@@ -129,6 +132,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/common/resource_type.h"
@@ -157,8 +161,6 @@ static const char* kSiteProcessMapKeyName = "content_site_process_map";
namespace content {
namespace {
-base::MessageLoop* g_in_process_thread;
-
void CacheShaderInfo(int32 id, base::FilePath path) {
ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
}
@@ -167,88 +169,30 @@ void RemoveShaderInfo(int32 id) {
ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
}
-} // namespace
-
-#if !defined(CHROME_MULTIPLE_DLL)
-
-// This class creates the IO thread for the renderer when running in
-// single-process mode. It's not used in multi-process mode.
-class RendererMainThread : public base::Thread {
- public:
- explicit RendererMainThread(const std::string& channel_id)
- : Thread("Chrome_InProcRendererThread"),
- channel_id_(channel_id) {
- }
-
- virtual ~RendererMainThread() {
- Stop();
- }
-
- protected:
- virtual void Init() OVERRIDE {
- render_process_.reset(new RenderProcessImpl());
- new RenderThreadImpl(channel_id_);
- g_in_process_thread = message_loop();
- }
-
- virtual void CleanUp() OVERRIDE {
- g_in_process_thread = NULL;
- render_process_.reset();
-
- // It's a little lame to manually set this flag. But the single process
- // RendererThread will receive the WM_QUIT. We don't need to assert on
- // this thread, so just force the flag manually.
- // If we want to avoid this, we could create the InProcRendererThread
- // directly with _beginthreadex() rather than using the Thread class.
- // We used to set this flag in the Init function above. However there
- // other threads like WebThread which are created by this thread
- // which resets this flag. Please see Thread::StartWithOptions. Setting
- // this flag to true in Cleanup works around these problems.
- SetThreadWasQuitProperly(true);
- }
-
- private:
- std::string channel_id_;
- scoped_ptr<RenderProcess> render_process_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
-};
-
-#endif
-
-namespace {
-
-// Helper class that we pass to ResourceMessageFilter so that it can find the
-// right net::URLRequestContext for a request.
-class RendererURLRequestContextSelector
- : public ResourceMessageFilter::URLRequestContextSelector {
- public:
- RendererURLRequestContextSelector(BrowserContext* browser_context,
- int render_child_id)
- : request_context_(browser_context->GetRequestContextForRenderProcess(
- render_child_id)),
- media_request_context_(
- browser_context->GetMediaRequestContextForRenderProcess(
- render_child_id)) {
- }
-
- virtual net::URLRequestContext* GetRequestContext(
- ResourceType::Type resource_type) OVERRIDE {
- net::URLRequestContextGetter* request_context = request_context_.get();
- // If the request has resource type of ResourceType::MEDIA, we use a request
- // context specific to media for handling it because these resources have
- // specific needs for caching.
- if (resource_type == ResourceType::MEDIA)
- request_context = media_request_context_.get();
- return request_context->GetURLRequestContext();
- }
-
- private:
- virtual ~RendererURLRequestContextSelector() {}
+net::URLRequestContext* GetRequestContext(
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ scoped_refptr<net::URLRequestContextGetter> media_request_context,
+ ResourceType::Type resource_type) {
+ // If the request has resource type of ResourceType::MEDIA, we use a request
+ // context specific to media for handling it because these resources have
+ // specific needs for caching.
+ if (resource_type == ResourceType::MEDIA)
+ return media_request_context->GetURLRequestContext();
+ return request_context->GetURLRequestContext();
+}
- scoped_refptr<net::URLRequestContextGetter> request_context_;
- scoped_refptr<net::URLRequestContextGetter> media_request_context_;
-};
+void GetContexts(
+ ResourceContext* resource_context,
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ scoped_refptr<net::URLRequestContextGetter> media_request_context,
+ const ResourceHostMsg_Request& request,
+ ResourceContext** resource_context_out,
+ net::URLRequestContext** request_context_out) {
+ *resource_context_out = resource_context;
+ *request_context_out =
+ GetRequestContext(request_context, media_request_context,
+ request.resource_type);
+}
// the global list of all renderer processes
base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
@@ -339,6 +283,20 @@ class RendererSandboxedProcessLauncherDelegate
} // namespace
+RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
+
+void RenderProcessHost::RegisterRendererMainThreadFactory(
+ RendererMainThreadFactoryFunction create) {
+ g_renderer_main_thread_factory = create;
+}
+
+base::MessageLoop* g_in_process_thread;
+
+base::MessageLoop*
+ RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
+ return g_in_process_thread;
+}
+
// Stores the maximum number of renderer processes the content module can
// create.
static size_t g_max_renderer_count_override = 0;
@@ -511,15 +469,14 @@ bool RenderProcessHostImpl::Init() {
CreateMessageFilters();
// Single-process mode not supported in multiple-dll mode currently.
-#if !defined(CHROME_MULTIPLE_DLL)
- if (run_renderer_in_process()) {
+ if (run_renderer_in_process() && g_renderer_main_thread_factory) {
// Crank up a thread and run the initialization there. With the way that
// messages flow between the browser and renderer, this thread is required
// to prevent a deadlock in single-process mode. Since the primordial
// thread in the renderer process runs the WebKit code and can sometimes
// make blocking calls to the UI thread (i.e. this thread), they need to run
// on separate threads.
- in_process_renderer_.reset(new RendererMainThread(channel_id));
+ in_process_renderer_.reset(g_renderer_main_thread_factory(channel_id));
base::Thread::Options options;
#if defined(OS_WIN) && !defined(OS_MACOSX)
@@ -532,10 +489,10 @@ bool RenderProcessHostImpl::Init() {
#endif
in_process_renderer_->StartWithOptions(options);
+ g_in_process_thread = in_process_renderer_->message_loop();
+
OnProcessLaunched(); // Fake a callback that the process is ready.
- } else
-#endif // !CHROME_MULTIPLE_DLL
- {
+ } else {
// Build command line for renderer. We call AppendRendererCommandLine()
// first so the process type argument will appear first.
CommandLine* cmd_line = new CommandLine(renderer_path);
@@ -552,7 +509,7 @@ bool RenderProcessHostImpl::Init() {
new RendererSandboxedProcessLauncherDelegate,
#elif defined(OS_POSIX)
renderer_prefix.empty(),
- base::EnvironmentVector(),
+ base::EnvironmentMap(),
channel_->TakeClientFileDescriptor(),
#endif
cmd_line,
@@ -604,12 +561,21 @@ void RenderProcessHostImpl::CreateMessageFilters() {
BrowserContext* browser_context = GetBrowserContext();
ResourceContext* resource_context = browser_context->GetResourceContext();
+ scoped_refptr<net::URLRequestContextGetter> request_context(
+ browser_context->GetRequestContextForRenderProcess(GetID()));
+ scoped_refptr<net::URLRequestContextGetter> media_request_context(
+ browser_context->GetMediaRequestContextForRenderProcess(GetID()));
+
+ ResourceMessageFilter::GetContextsCallback get_contexts_callback(
+ base::Bind(&GetContexts, browser_context->GetResourceContext(),
+ request_context, media_request_context));
+
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
- GetID(), PROCESS_TYPE_RENDERER, resource_context,
+ GetID(), PROCESS_TYPE_RENDERER,
storage_partition_impl_->GetAppCacheService(),
ChromeBlobStorageContext::GetFor(browser_context),
storage_partition_impl_->GetFileSystemContext(),
- new RendererURLRequestContextSelector(browser_context, GetID()));
+ get_contexts_callback);
channel_->AddFilter(resource_message_filter);
MediaStreamManager* media_stream_manager =
@@ -617,13 +583,16 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new AudioInputRendererHost(
audio_manager,
media_stream_manager,
- BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
+ BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
+ BrowserMainLoop::GetInstance()->user_input_monitor()));
channel_->AddFilter(new AudioRendererHost(
- GetID(), audio_manager,
+ GetID(),
+ audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
- media_internals, media_stream_manager));
+ media_internals,
+ media_stream_manager));
channel_->AddFilter(
- new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
+ new MIDIHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
channel_->AddFilter(new MIDIDispatcherHost(GetID(), browser_context));
channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
channel_->AddFilter(new AppCacheDispatcherHost(
@@ -636,6 +605,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new IndexedDBDispatcherHost(
GetID(),
storage_partition_impl_->GetIndexedDBContext()));
+ channel_->AddFilter(new ServiceWorkerDispatcherHost(
+ storage_partition_impl_->GetServiceWorkerContext()));
if (IsGuest()) {
if (!g_browser_plugin_geolocation_context.Get().get()) {
g_browser_plugin_geolocation_context.Get() =
@@ -660,8 +631,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
new DeviceRequestMessageFilter(resource_context, media_stream_manager));
#endif
#if defined(ENABLE_PLUGINS)
- // TODO(raymes): PepperMessageFilter should be removed from here.
- channel_->AddFilter(new PepperMessageFilter(GetID(), browser_context));
channel_->AddFilter(new PepperRendererConnection(GetID()));
#endif
#if defined(ENABLE_INPUT_SPEECH)
@@ -685,12 +654,19 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
#elif defined(OS_WIN)
channel_->AddFilter(new FontCacheDispatcher());
+#elif defined(OS_ANDROID)
+ browser_demuxer_android_ = new BrowserDemuxerAndroid();
+ channel_->AddFilter(browser_demuxer_android_);
#endif
+ SocketStreamDispatcherHost::GetRequestContextCallback
+ request_context_callback(
+ base::Bind(&GetRequestContext, request_context,
+ media_request_context));
+
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
- new SocketStreamDispatcherHost(GetID(),
- new RendererURLRequestContextSelector(browser_context, GetID()),
- resource_context);
+ new SocketStreamDispatcherHost(
+ GetID(), request_context_callback, resource_context);
channel_->AddFilter(socket_stream_dispatcher_host);
channel_->AddFilter(new WorkerMessageFilter(
@@ -856,6 +832,15 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
field_trial_states);
}
+ if (content::IsThreadedCompositingEnabled())
+ command_line->AppendSwitch(switches::kEnableThreadedCompositing);
+
+ if (content::IsDelegatedRendererEnabled())
+ command_line->AppendSwitch(switches::kEnableDelegatedRenderer);
+
+ if (content::IsDeadlineSchedulingEnabled())
+ command_line->AppendSwitch(switches::kEnableDeadlineScheduling);
+
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
command_line, GetID());
@@ -875,6 +860,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kAudioBufferSize,
switches::kAuditAllHandles,
switches::kAuditHandles,
+ switches::kBlockCrossSiteDocuments,
+ switches::kDirectNPAPIRequests,
switches::kDisable3DAPIs,
switches::kDisableAcceleratedCompositing,
switches::kDisableAcceleratedVideoDecode,
@@ -882,6 +869,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableAudio,
switches::kDisableBreakpad,
switches::kDisableDatabases,
+ switches::kDisableDeadlineScheduling,
switches::kDisableDelegatedRenderer,
switches::kDisableDesktopNotifications,
switches::kDisableDeviceOrientation,
@@ -894,7 +882,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableHistogramCustomizer,
switches::kDisableLocalStorage,
switches::kDisableLogging,
- switches::kDisableNewDialogStyle,
switches::kDisableSeccompFilterSandbox,
switches::kDisableSessionStorage,
switches::kDisableSharedWorkers,
@@ -908,7 +895,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableWebAudio,
#if defined(ENABLE_WEBRTC)
switches::kDisableDeviceEnumeration,
- switches::kEnableSCTPDataChannels,
+ switches::kDisableSCTPDataChannels,
+ switches::kDisableWebRtcHWDecoding,
+ switches::kDisableWebRtcHWEncoding,
#endif
switches::kEnableWebAnimationsCSS,
switches::kEnableWebAnimationsSVG,
@@ -921,10 +910,15 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableBrowserInputController,
switches::kEnableBrowserPluginForAllViewTypes,
switches::kEnableDCHECK,
+ switches::kEnableDeadlineScheduling,
switches::kEnableDelegatedRenderer,
switches::kEnableEncryptedMedia,
switches::kDisableLegacyEncryptedMedia,
switches::kOverrideEncryptedMediaCanPlayType,
+#if defined(OS_ANDROID)
+ switches::kEnableMediaDrm,
+ switches::kMediaDrmEnableNonCompositing,
+#endif
switches::kEnableExperimentalWebPlatformFeatures,
switches::kEnableFixedLayout,
switches::kEnableDeferredImageDecoding,
@@ -932,7 +926,12 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGpuBenchmarking,
+#if defined(OS_WIN)
+ switches::kEnableHighResolutionTime,
+#endif
+ switches::kEnableMP3StreamParser,
switches::kEnableMemoryBenchmarking,
+ switches::kEnableOverlayFullscreenVideo,
switches::kEnableOverlayScrollbars,
switches::kEnableSkiaBenchmarking,
switches::kEnableLogging,
@@ -942,13 +941,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(ENABLE_WEBRTC)
switches::kEnableWebRtcAecRecordings,
switches::kEnableWebRtcTcpServerSocket,
- switches::kEnableWebRtcHWDecoding,
#endif
switches::kDisableWebKitMediaSource,
switches::kEnableOverscrollNotifications,
switches::kEnableStrictSiteIsolation,
switches::kDisableFullScreen,
- switches::kEnableNewDialogStyle,
#if defined(ENABLE_PLUGINS)
switches::kEnablePepperTesting,
switches::kDisablePepper3d,
@@ -981,7 +978,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableViewport,
switches::kEnableInbandTextTracks,
switches::kEnableOpusPlayback,
- switches::kEnableVp8AlphaPlayback,
+ switches::kDisableVp8AlphaPlayback,
switches::kEnableEac3Playback,
switches::kForceDeviceScaleFactor,
switches::kFullMemoryCrashReport,
@@ -1030,19 +1027,21 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kWebCoreLogChannels,
switches::kEnableWebGLDraftExtensions,
switches::kEnableHTMLImports,
+ switches::kEnableInputModeAttribute,
switches::kTraceToConsole,
- switches::kEnableDeviceMotion,
-#if defined(OS_ANDROID)
switches::kDisableDeviceMotion,
-#endif
// Please keep these in alphabetical order. Compositor switches here should
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kBackgroundColorInsteadOfCheckerboard,
cc::switches::kCompositeToMailbox,
cc::switches::kDisableCompositedAntialiasing,
cc::switches::kDisableImplSidePainting,
+ cc::switches::kDisableLCDText,
+ cc::switches::kDisableMapImage,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableImplSidePainting,
+ cc::switches::kEnableLCDText,
+ cc::switches::kEnableMapImage,
cc::switches::kEnablePartialSwap,
cc::switches::kEnablePerTilePainting,
cc::switches::kEnablePinchVirtualViewport,
@@ -1066,7 +1065,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kTopControlsHideThreshold,
cc::switches::kTopControlsShowThreshold,
cc::switches::kTraceOverdraw,
- cc::switches::kUseMapImage,
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
@@ -1249,7 +1247,6 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
// Adding single handlers for your service here is fine, but once your
// service needs more than one handler, please extract them into a new
// message filter and add that filter to CreateMessageFilters().
- IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP_EX()
if (!msg_is_ok) {
@@ -1613,11 +1610,6 @@ void RenderProcessHostImpl::RegisterProcessHostForSite(
map->RegisterProcess(site, process);
}
-base::MessageLoop*
- RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
- return g_in_process_thread;
-}
-
void RenderProcessHostImpl::ProcessDied(bool already_dead) {
// Our child process has died. If we didn't expect it, it's a crash.
// In any case, we need to let everyone know it's gone.
@@ -1661,10 +1653,11 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
int RenderProcessHostImpl::GetActiveViewCount() {
int num_active_views = 0;
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Count only RenderWidgetHosts in this process.
- if (widgets[i]->GetProcess()->GetID() == GetID())
+ if (widget->GetProcess()->GetID() == GetID())
num_active_views++;
}
return num_active_views;
@@ -1797,17 +1790,17 @@ void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
void RenderProcessHostImpl::OnGpuSwitching() {
// We are updating all widgets including swapped out ones.
- RenderWidgetHost::List widgets =
- RenderWidgetHostImpl::GetAllRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (!widgets[i]->IsRenderView())
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (!widget->IsRenderView())
continue;
// Skip widgets in other processes.
- if (widgets[i]->GetProcess()->GetID() != GetID())
+ if (widget->GetProcess()->GetID() != GetID())
continue;
- RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
+ RenderViewHost* rvh = RenderViewHost::From(widget);
rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
}
}
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index 72ec846303d..0e9ae1b2ad1 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -33,6 +33,7 @@ class Size;
}
namespace content {
+class BrowserDemuxerAndroid;
class GpuMessageFilter;
class PeerConnectionTrackerHost;
class RendererMainThread;
@@ -177,6 +178,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
static base::MessageLoop* GetInProcessRendererThreadForTesting();
+#if defined(OS_ANDROID)
+ const scoped_refptr<BrowserDemuxerAndroid>& browser_demuxer_android() {
+ return browser_demuxer_android_;
+ }
+#endif
+
protected:
// A proxy for our IPC::Channel that lives on the IO thread (see
// browser_process.h)
@@ -264,10 +271,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// This is used to clear our cache five seconds after the last use.
base::DelayTimer<RenderProcessHostImpl> cached_dibs_cleaner_;
-#if !defined(CHROME_MULTIPLE_DLL)
// Used in single-process mode.
- scoped_ptr<RendererMainThread> in_process_renderer_;
-#endif
+ scoped_ptr<base::Thread> in_process_renderer_;
// True after Init() has been called. We can't just check channel_ because we
// also reset that in the case of process termination.
@@ -324,6 +329,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Forwards power state messages to the renderer process.
PowerMonitorMessageBroadcaster power_monitor_broadcaster_;
+#if defined(OS_ANDROID)
+ scoped_refptr<BrowserDemuxerAndroid> browser_demuxer_android_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
};
diff --git a/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc b/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
index 87d31dca88c..81537181532 100644
--- a/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
@@ -30,6 +30,8 @@
#include "content/child/webkitplatformsupport_impl.h"
#include "content/common/font_config_ipc_linux.h"
#include "content/common/sandbox_linux.h"
+#include "content/common/set_process_title.h"
+#include "content/public/common/content_switches.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/linux/WebFontInfo.h"
@@ -71,6 +73,15 @@ class SandboxIPCProcess {
// positioning, so we pass the current setting through to WebKit.
WebFontInfo::setSubpixelPositioning(
gfx::GetDefaultWebkitSubpixelPositioning());
+
+ CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ command_line.AppendSwitchASCII(switches::kProcessType,
+ switches::kSandboxIPCProcess);
+
+ // Update the process title. The argv was already cached by the call to
+ // SetProcessTitleFromCommandLine in content_main_runner.cc, so we can pass
+ // NULL here (we don't have the original argv at this point).
+ SetProcessTitleFromCommandLine(NULL);
}
~SandboxIPCProcess();
diff --git a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
index 4255d055ce1..20fec727501 100644
--- a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -13,7 +13,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/host_port_pair.h"
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index 5ce2a44d716..997452aeb54 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -50,6 +50,7 @@ class PageState;
class RenderViewHost;
class RenderViewHostDelegateView;
class SessionStorageNamespace;
+class SiteInstance;
class WebContents;
class WebContentsImpl;
struct ContextMenuParams;
@@ -58,7 +59,8 @@ struct GlobalRequestID;
struct NativeWebKeyboardEvent;
struct Referrer;
struct RendererPreferences;
-class SiteInstance;
+struct ResourceRedirectDetails;
+struct ResourceRequestDetails;
//
// RenderViewHostDelegate
@@ -151,8 +153,8 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// The RenderView processed a redirect during a provisional load.
//
// TODO(creis): Remove this method and have the pre-rendering code listen to
- // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
- // instead. See http://crbug.com/78512.
+ // WebContentsObserver::DidGetRedirectForResourceRequest instead.
+ // See http://crbug.com/78512.
virtual void DidRedirectProvisionalLoad(
RenderViewHost* render_view_host,
int32 page_id,
@@ -164,6 +166,14 @@ class CONTENT_EXPORT RenderViewHostDelegate {
RenderViewHost* render_view_host,
const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {}
+ // A response has been received for a resource request.
+ virtual void DidGetResourceResponseStart(
+ const ResourceRequestDetails& details) {}
+
+ // A redirect was received while requesting a resource.
+ virtual void DidGetRedirectForResourceRequest(
+ const ResourceRedirectDetails& details) {}
+
// The RenderView was navigated to a different page.
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params) {}
@@ -299,6 +309,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// Notification that the renderer has become unresponsive. The
// delegate can use this notification to show a warning to the user.
virtual void RendererUnresponsive(RenderViewHost* render_view_host,
+ bool is_during_before_unload,
bool is_during_unload) {}
// Notification that a previously unresponsive renderer has become
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.cc b/chromium/content/browser/renderer_host/render_view_host_factory.cc
index 20d15d38f0c..5cffd134b8e 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -19,14 +19,15 @@ RenderViewHost* RenderViewHostFactory::Create(
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out) {
+ bool swapped_out,
+ bool hidden) {
if (factory_) {
return factory_->CreateRenderViewHost(instance, delegate, widget_delegate,
routing_id, main_frame_routing_id,
swapped_out);
}
return new RenderViewHostImpl(instance, delegate, widget_delegate, routing_id,
- main_frame_routing_id, swapped_out);
+ main_frame_routing_id, swapped_out, hidden);
}
// static
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.h b/chromium/content/browser/renderer_host/render_view_host_factory.h
index 6226187af53..b0466355d49 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -29,7 +29,8 @@ class RenderViewHostFactory {
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out);
+ bool swapped_out,
+ bool hidden);
// Returns true if there is currently a globally-registered factory.
static bool has_factory() {
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.cc b/chromium/content/browser/renderer_host/render_view_host_impl.cc
index 56801c03c18..68204fb746a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -51,6 +51,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host_observer.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
@@ -72,7 +73,7 @@
#if defined(OS_MACOSX)
#include "content/browser/renderer_host/popup_menu_helper_mac.h"
#elif defined(OS_ANDROID)
-#include "media/base/android/media_player_manager.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
#endif
using base::TimeDelta;
@@ -116,11 +117,7 @@ g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
// static
RenderViewHost* RenderViewHost::FromID(int render_process_id,
int render_view_id) {
- RenderWidgetHost* widget =
- RenderWidgetHost::FromID(render_process_id, render_view_id);
- if (!widget || !widget->IsRenderView())
- return NULL;
- return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
+ return RenderViewHostImpl::FromID(render_process_id, render_view_id);
}
// static
@@ -143,8 +140,11 @@ void RenderViewHost::FilterURL(const RenderProcessHost* process,
// static
RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
int render_view_id) {
- return static_cast<RenderViewHostImpl*>(
- RenderViewHost::FromID(render_process_id, render_view_id));
+ RenderWidgetHost* widget =
+ RenderWidgetHost::FromID(render_process_id, render_view_id);
+ if (!widget || !widget->IsRenderView())
+ return NULL;
+ return static_cast<RenderViewHostImpl*>(RenderWidgetHostImpl::From(widget));
}
RenderViewHostImpl::RenderViewHostImpl(
@@ -153,8 +153,12 @@ RenderViewHostImpl::RenderViewHostImpl(
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out)
- : RenderWidgetHostImpl(widget_delegate, instance->GetProcess(), routing_id),
+ bool swapped_out,
+ bool hidden)
+ : RenderWidgetHostImpl(widget_delegate,
+ instance->GetProcess(),
+ routing_id,
+ hidden),
delegate_(delegate),
instance_(static_cast<SiteInstanceImpl*>(instance)),
waiting_for_drag_context_response_(false),
@@ -191,7 +195,7 @@ RenderViewHostImpl::RenderViewHostImpl(
instance_->increment_active_view_count();
#if defined(OS_ANDROID)
- media_player_manager_ = media::MediaPlayerManager::Create(this);
+ media_player_manager_ = BrowserMediaPlayerManager::Create(this);
#endif
}
@@ -259,6 +263,7 @@ bool RenderViewHostImpl::CreateRenderView(
// Ensure the RenderView sets its opener correctly.
params.opener_route_id = opener_route_id;
params.swapped_out = is_swapped_out_;
+ params.hidden = is_hidden();
params.next_page_id = next_page_id;
GetWebScreenInfo(&params.screen_info);
params.accessibility_mode = accessibility_mode();
@@ -338,7 +343,7 @@ void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
//
// WebKit doesn't send throb notifications for JavaScript URLs, so we
// don't want to either.
- if (!params.url.SchemeIs(chrome::kJavaScriptScheme))
+ if (!params.url.SchemeIs(kJavaScriptScheme))
delegate_->DidStartLoading(this);
FOR_EACH_OBSERVER(RenderViewHostObserver, observers_, Navigate(params.url));
@@ -479,9 +484,10 @@ void RenderViewHostImpl::WasSwappedOut() {
// Count the number of active widget hosts for the process, which
// is equivalent to views using the process as of this writing.
- RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
- for (size_t i = 0; i < widgets.size(); ++i) {
- if (widgets[i]->GetProcess()->GetID() == GetProcess()->GetID())
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHost::GetRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ if (widget->GetProcess()->GetID() == GetProcess()->GetID())
++views;
}
@@ -736,7 +742,8 @@ void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
// This must be done after sending the reply since RenderView can't close
// correctly while waiting for a response.
if (is_waiting && are_javascript_messages_suppressed_)
- delegate_->RendererUnresponsive(this, is_waiting);
+ delegate_->RendererUnresponsive(
+ this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
}
void RenderViewHostImpl::DragSourceEndedAt(
@@ -763,6 +770,12 @@ void RenderViewHostImpl::DragSourceSystemDragEnded() {
}
void RenderViewHostImpl::AllowBindings(int bindings_flags) {
+ // Never grant any bindings to browser plugin guests.
+ if (GetProcess()->IsGuest()) {
+ NOTREACHED() << "Never grant bindings to a guest process.";
+ return;
+ }
+
// Ensure we aren't granting WebUI bindings to a process that has already
// been used for non-privileged views.
if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
@@ -777,12 +790,6 @@ void RenderViewHostImpl::AllowBindings(int bindings_flags) {
return;
}
- // Never grant any bindings to browser plugin guests.
- if (GetProcess()->IsGuest()) {
- NOTREACHED() << "Never grant bindings to a guest process.";
- return;
- }
-
if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
GetProcess()->GetID());
@@ -999,8 +1006,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnDidAccessInitialDocument)
IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
OnDomOperationResponse)
- IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Notifications,
- OnAccessibilityNotifications)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(
handled = RenderWidgetHostImpl::OnMessageReceived(msg))
@@ -1016,6 +1022,11 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+void RenderViewHostImpl::Init() {
+ RenderWidgetHostImpl::Init();
+ main_render_frame_host()->Init();
+}
+
void RenderViewHostImpl::Shutdown() {
// If we are being run modally (see RunModal), then we need to cleanup.
if (run_modal_reply_msg_) {
@@ -1239,8 +1250,6 @@ void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) {
FilterURL(policy, process, false, &(*it));
}
FilterURL(policy, process, true, &validated_params.searchable_form_url);
- FilterURL(policy, process, true, &validated_params.password_form.origin);
- FilterURL(policy, process, true, &validated_params.password_form.action);
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
@@ -1354,6 +1363,8 @@ void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
delegate_->ToggleFullscreenMode(enter_fullscreen);
+ // We need to notify the contents that its fullscreen state has changed. This
+ // is done as part of the resize message.
WasResized();
}
@@ -1399,7 +1410,7 @@ void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
void RenderViewHostImpl::OnSelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
if (view_)
view_->SelectionChanged(text, offset, range);
}
@@ -1464,7 +1475,7 @@ void RenderViewHostImpl::OnStartDragging(
ChildProcessSecurityPolicyImpl::GetInstance();
// Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
- if (!filtered_data.url.SchemeIs(chrome::kJavaScriptScheme))
+ if (!filtered_data.url.SchemeIs(kJavaScriptScheme))
FilterURL(policy, process, true, &filtered_data.url);
FilterURL(policy, process, false, &filtered_data.html_base_url);
// Filter out any paths that the renderer didn't have access to. This prevents
@@ -1522,6 +1533,7 @@ void RenderViewHostImpl::OnAddMessageToConsole(
const string16& source_id) {
if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
return;
+
// Pass through log level only on WebUI pages to limit console spew.
int32 resolved_level = HasWebUIScheme(delegate_->GetURL()) ? level : 0;
@@ -1595,7 +1607,7 @@ void RenderViewHostImpl::OnClosePageACK() {
void RenderViewHostImpl::NotifyRendererUnresponsive() {
delegate_->RendererUnresponsive(
- this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
+ this, is_waiting_for_beforeunload_ack_, is_waiting_for_unload_ack_);
}
void RenderViewHostImpl::NotifyRendererResponsive() {
@@ -1772,9 +1784,8 @@ void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
void RenderViewHostImpl::ExitFullscreen() {
RejectMouseLockOrUnlockIfNecessary();
- // We need to notify the contents that its fullscreen state has changed. This
- // is done as part of the resize message.
- WasResized();
+ // Notify delegate_ and renderer of fullscreen state change.
+ OnToggleFullscreen(false);
}
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
@@ -1789,7 +1800,7 @@ void RenderViewHostImpl::DisownOpener() {
}
void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
- const base::Callback<void(AccessibilityNotification)>& callback) {
+ const base::Callback<void(WebKit::WebAXEvent)>& callback) {
accessibility_testing_callback_ = callback;
}
@@ -1871,10 +1882,6 @@ void RenderViewHostImpl::ExecutePluginActionAtLocation(
Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
}
-void RenderViewHostImpl::DisassociateFromPopupCount() {
- Send(new ViewMsg_DisassociateFromPopupCount(GetRoutingID()));
-}
-
void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
}
@@ -1883,13 +1890,13 @@ void RenderViewHostImpl::StopFinding(StopFindAction action) {
Send(new ViewMsg_StopFinding(GetRoutingID(), action));
}
-void RenderViewHostImpl::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderViewHostImpl::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (view_ && !is_swapped_out_)
- view_->OnAccessibilityNotifications(params);
+ view_->OnAccessibilityEvents(params);
// Always send an ACK or the renderer can be in a bad state.
- Send(new AccessibilityMsg_Notifications_ACK(GetRoutingID()));
+ Send(new AccessibilityMsg_Events_ACK(GetRoutingID()));
// The rest of this code is just for testing; bail out if we're not
// in that mode.
@@ -1897,10 +1904,10 @@ void RenderViewHostImpl::OnAccessibilityNotifications(
return;
for (unsigned i = 0; i < params.size(); i++) {
- const AccessibilityHostMsg_NotificationParams& param = params[i];
- AccessibilityNotification src_type = param.notification_type;
- if (src_type == AccessibilityNotificationLayoutComplete ||
- src_type == AccessibilityNotificationLoadComplete) {
+ const AccessibilityHostMsg_EventParams& param = params[i];
+ WebKit::WebAXEvent src_type = param.event_type;
+ if (src_type == WebKit::WebAXEventLayoutComplete ||
+ src_type == WebKit::WebAXEventLoadComplete) {
MakeAccessibilityNodeDataTree(param.nodes, &accessibility_tree_);
}
accessibility_testing_callback_.Run(src_type);
@@ -1953,7 +1960,7 @@ void RenderViewHostImpl::OnShowDesktopNotification(
// allows unwanted cross-domain access.
GURL url = params.contents_url;
if (params.is_html &&
- (url.SchemeIs(chrome::kJavaScriptScheme) ||
+ (url.SchemeIs(kJavaScriptScheme) ||
url.SchemeIs(chrome::kFileScheme))) {
return;
}
@@ -2024,6 +2031,11 @@ void RenderViewHostImpl::OnShowPopup(
}
#endif
+RenderFrameHostImpl* RenderViewHostImpl::main_render_frame_host() const {
+ DCHECK_EQ(GetProcess(), main_render_frame_host_->GetProcess());
+ return main_render_frame_host_.get();
+}
+
void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
// We update the number of RenderViews in a SiteInstance when the
// swapped out status of this RenderView gets flipped.
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.h b/chromium/content/browser/renderer_host/render_view_host_impl.h
index 20caaf5ea73..c4bfb7876d1 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -18,22 +18,22 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/accessibility_node_data.h"
-#include "content/common/accessibility_notification.h"
#include "content/common/drag_event_source_info.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/window_container_type.h"
#include "net/base/load_states.h"
-#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/window_open_disposition.h"
class SkBitmap;
class ViewMsg_Navigate;
-struct AccessibilityHostMsg_NotificationParams;
+struct AccessibilityHostMsg_EventParams;
struct MediaPlayerAction;
struct ViewHostMsg_CreateWindow_Params;
struct ViewHostMsg_DidFailProvisionalLoadWithError_Params;
@@ -48,19 +48,17 @@ namespace base {
class ListValue;
}
-namespace ui {
+namespace gfx {
class Range;
-struct SelectedFileInfo;
}
-#if defined(OS_ANDROID)
-namespace media {
-class MediaPlayerManager;
+namespace ui {
+struct SelectedFileInfo;
}
-#endif
namespace content {
+class BrowserMediaPlayerManager;
class ChildProcessSecurityPolicyImpl;
class PageState;
class RenderFrameHostImpl;
@@ -110,7 +108,8 @@ class CONTENT_EXPORT RenderViewHostImpl
// |routing_id| could be a valid route id, or it could be MSG_ROUTING_NONE, in
// which case RenderWidgetHost will create a new one. |swapped_out| indicates
// whether the view should initially be swapped out (e.g., for an opener
- // frame being rendered by another process).
+ // frame being rendered by another process). |hidden| indicates whether the
+ // view is initially hidden or visible.
//
// The |session_storage_namespace| parameter allows multiple render views and
// WebContentses to share the same session storage (part of the WebStorage
@@ -123,7 +122,8 @@ class CONTENT_EXPORT RenderViewHostImpl
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out);
+ bool swapped_out,
+ bool hidden);
virtual ~RenderViewHostImpl();
// RenderViewHost implementation.
@@ -131,7 +131,6 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void ClearFocusedNode() OVERRIDE;
virtual void ClosePage() OVERRIDE;
virtual void CopyImageAt(int x, int y) OVERRIDE;
- virtual void DisassociateFromPopupCount() OVERRIDE;
virtual void DesktopNotificationPermissionRequestDone(
int callback_context) OVERRIDE;
virtual void DesktopNotificationPostDisplay(int callback_context) OVERRIDE;
@@ -354,6 +353,7 @@ class CONTENT_EXPORT RenderViewHostImpl
}
// RenderWidgetHost public overrides.
+ virtual void Init() OVERRIDE;
virtual void Shutdown() OVERRIDE;
virtual bool IsRenderView() const OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
@@ -388,7 +388,7 @@ class CONTENT_EXPORT RenderViewHostImpl
#endif
#if defined(OS_ANDROID)
- media::MediaPlayerManager* media_player_manager() {
+ BrowserMediaPlayerManager* media_player_manager() {
return media_player_manager_;
}
@@ -417,7 +417,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// renderer process, and the accessibility tree it sent can be
// retrieved using accessibility_tree_for_testing().
void SetAccessibilityCallbackForTesting(
- const base::Callback<void(AccessibilityNotification)>& callback);
+ const base::Callback<void(WebKit::WebAXEvent)>& callback);
// Only valid if SetAccessibilityCallbackForTesting was called and
// the callback was run at least once. Returns a snapshot of the
@@ -526,7 +526,7 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnDidChangeNumWheelEvents(int count);
void OnSelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range);
+ const gfx::Range& range);
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnPasteFromSelectionClipboard();
@@ -562,8 +562,8 @@ class CONTENT_EXPORT RenderViewHostImpl
const base::TimeTicks& renderer_before_unload_end_time);
void OnClosePageACK();
void OnSwapOutACK();
- void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params);
+ void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params);
void OnScriptEvalResponse(int id, const base::ListValue& result);
void OnDidZoomURL(double zoom_level, bool remember, const GURL& url);
void OnRequestDesktopNotificationPermission(const GURL& origin,
@@ -584,6 +584,11 @@ class CONTENT_EXPORT RenderViewHostImpl
private:
friend class TestRenderViewHost;
FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, BasicRenderFrameHost);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, RoutingIdSane);
+
+ // TODO(nasko): Remove this accessor once RenderFrameHost moves into the frame
+ // tree.
+ RenderFrameHostImpl* main_render_frame_host() const;
// Sets whether this RenderViewHost is swapped out in favor of another,
// and clears any waiting state that is no longer relevant.
@@ -678,8 +683,7 @@ class CONTENT_EXPORT RenderViewHostImpl
std::map<int, JavascriptResultCallback> javascript_callbacks_;
// Accessibility callback for testing.
- base::Callback<void(AccessibilityNotification)>
- accessibility_testing_callback_;
+ base::Callback<void(WebKit::WebAXEvent)> accessibility_testing_callback_;
// The most recently received accessibility tree - for testing only.
AccessibilityNodeDataTreeNode accessibility_tree_;
@@ -699,7 +703,7 @@ class CONTENT_EXPORT RenderViewHostImpl
#if defined(OS_ANDROID)
// Manages all the android mediaplayer objects and handling IPCs for video.
// This class inherits from RenderViewHostObserver.
- media::MediaPlayerManager* media_player_manager_;
+ BrowserMediaPlayerManager* media_player_manager_;
#endif
DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
index 4053d6593f2..55785d07859 100644
--- a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
@@ -25,7 +25,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -86,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -153,7 +153,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the window to open.
Shell* new_shell = new_shell_observer.GetShell();
- EXPECT_EQ("/files/title2.html", new_shell->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ new_shell->web_contents()->GetVisibleURL().path());
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
@@ -207,7 +208,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
Shell* new_shell = new_shell_observer.GetShell();
// Opens in new window.
- EXPECT_EQ("/files/title2.html", new_shell->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ new_shell->web_contents()->GetVisibleURL().path());
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
@@ -262,7 +264,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the cross-site transition in the new tab to finish.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title2.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -308,7 +310,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Opens in same window.
EXPECT_EQ(1u, Shell::windows().size());
- EXPECT_EQ("/files/title2.html", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ shell()->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> noref_site_instance(
@@ -376,7 +379,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -421,7 +424,13 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test that setting the opener to null in a window affects cross-process
// navigations, including those to existing entries. http://crbug.com/156669.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownOpener) {
+// Flaky on windows: http://crbug.com/291249
+#if defined(OS_WIN)
+#define MAYBE_DisownOpener DISABLED_DisownOpener
+#else
+#define MAYBE_DisownOpener DisownOpener
+#endif
+IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, MAYBE_DisownOpener) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
@@ -456,7 +465,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownOpener) {
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title2.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -562,7 +571,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// send it to post_message.html on a different site.
WebContents* foo_contents = new_shell->web_contents();
WaitForLoadStop(foo_contents);
- EXPECT_EQ("/files/navigate_opener.html", foo_contents->GetURL().path());
+ EXPECT_EQ("/files/navigate_opener.html",
+ foo_contents->GetLastCommittedURL().path());
NavigateToURL(new_shell, https_server.GetURL("files/post_message.html"));
scoped_refptr<SiteInstance> foo_site_instance(
foo_contents->GetSiteInstance());
@@ -581,7 +591,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
Shell* new_shell2 = new_shell_observer2.GetShell();
WebContents* new_contents = new_shell2->web_contents();
WaitForLoadStop(new_contents);
- EXPECT_EQ("/files/title2.html", new_contents->GetURL().path());
+ EXPECT_EQ("/files/title2.html", new_contents->GetLastCommittedURL().path());
NavigateToURL(new_shell2, test_server()->GetURL("files/post_message.html"));
EXPECT_EQ(orig_site_instance, new_contents->GetSiteInstance());
RenderViewHostManager* new_manager =
@@ -698,7 +708,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> blank_site_instance(
@@ -765,7 +775,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> opened_site_instance(
@@ -829,7 +839,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
scoped_refptr<SiteInstance> post_nav_site_instance(
shell()->web_contents()->GetSiteInstance());
EXPECT_EQ(orig_site_instance, post_nav_site_instance);
- EXPECT_EQ("/nocontent", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/nocontent",
+ shell()->web_contents()->GetVisibleURL().path());
EXPECT_EQ("/files/click-noreferrer-links.html",
shell()->web_contents()->GetController().
GetLastCommittedEntry()->GetVirtualURL().path());
@@ -847,7 +858,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
// Opens in same tab.
EXPECT_EQ(1u, Shell::windows().size());
- EXPECT_EQ("/files/title2.html", shell()->web_contents()->GetURL().path());
+ EXPECT_EQ("/files/title2.html",
+ shell()->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
scoped_refptr<SiteInstance> noref_site_instance(
@@ -1073,7 +1085,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
@@ -1104,7 +1116,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
}
EXPECT_EQ("/files/navigate_opener.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
EXPECT_EQ(rvh, new_shell->web_contents()->GetRenderViewHost());
@@ -1187,7 +1199,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
// view-source URL, we create a new SiteInstance.
RenderViewHost* blank_rvh = shell()->web_contents()->GetRenderViewHost();
SiteInstance* blank_site_instance = blank_rvh->GetSiteInstance();
- EXPECT_EQ(shell()->web_contents()->GetURL(), GURL::EmptyGURL());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
EXPECT_EQ(blank_site_instance->GetSiteURL(), GURL::EmptyGURL());
rvh_observers.AddObserverToRVH(blank_rvh);
@@ -1269,7 +1281,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Wait for the navigation in the new window to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ("/files/title1.html",
- new_shell->web_contents()->GetURL().path());
+ new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
@@ -1286,7 +1298,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Make sure it ends up at the right page.
WaitForLoadStop(shell()->web_contents());
EXPECT_EQ(https_server.GetURL("files/title1.html"),
- shell()->web_contents()->GetURL());
+ shell()->web_contents()->GetLastCommittedURL());
EXPECT_EQ(new_site_instance, shell()->web_contents()->GetSiteInstance());
}
diff --git a/chromium/content/browser/renderer_host/render_view_host_unittest.cc b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
index a38e0446f3d..f4d694fae42 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -288,4 +288,11 @@ TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
EXPECT_EQ(1, process()->bad_msg_count());
}
+TEST_F(RenderViewHostTest, RoutingIdSane) {
+ EXPECT_EQ(test_rvh()->GetProcess(),
+ test_rvh()->main_render_frame_host()->GetProcess());
+ EXPECT_NE(test_rvh()->GetRoutingID(),
+ test_rvh()->main_render_frame_host()->routing_id());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
index 9f11299b1a6..bfdf6a5450a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -7,7 +7,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "net/base/net_util.h"
@@ -46,8 +46,14 @@ class RenderWidgetHostBrowserTest : public ContentBrowserTest {
base::FilePath test_dir_;
};
+// Disabled on Windows and CrOS because it is flaky: crbug.com/272379.
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+#define MAYBE_GetSnapshotFromRendererTest DISABLED_GetSnapshotFromRendererTest
+#else
+#define MAYBE_GetSnapshotFromRendererTest GetSnapshotFromRendererTest
+#endif
IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
- GetSnapshotFromRendererTest) {
+ MAYBE_GetSnapshotFromRendererTest) {
base::RunLoop run_loop;
NavigateToURL(shell(), GURL(net::FilePathToFileURL(
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
index edd21fe5987..4fce8d8cb2d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -22,12 +22,14 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/backing_store.h"
#include "content/browser/renderer_host/backing_store_manager.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/input/buffered_input_router.h"
#include "content/browser/renderer_host/input/immediate_input_router.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -40,10 +42,10 @@
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
@@ -51,8 +53,8 @@
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "ui/base/events/event.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -91,15 +93,50 @@ const int kPaintMsgTimeoutMS = 50;
base::LazyInstance<std::vector<RenderWidgetHost::CreatedCallback> >
g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-
typedef std::pair<int32, int32> RenderWidgetHostID;
typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
RoutingIDWidgetMap;
-static base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
+base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
LAZY_INSTANCE_INITIALIZER;
+// Implements the RenderWidgetHostIterator interface. It keeps a list of
+// RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
+// iteration (or NULL if there isn't any left).
+class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
+ public:
+ RenderWidgetHostIteratorImpl()
+ : current_index_(0) {
+ }
+
+ virtual ~RenderWidgetHostIteratorImpl() {
+ }
+
+ void Add(RenderWidgetHost* host) {
+ hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
+ host->GetRoutingID()));
+ }
+
+ // RenderWidgetHostIterator:
+ virtual RenderWidgetHost* GetNextHost() OVERRIDE {
+ RenderWidgetHost* host = NULL;
+ while (current_index_ < hosts_.size() && !host) {
+ RenderWidgetHostID id = hosts_[current_index_];
+ host = RenderWidgetHost::FromID(id.first, id.second);
+ ++current_index_;
+ }
+ return host;
+ }
+
+ private:
+ std::vector<RenderWidgetHostID> hosts_;
+ size_t current_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
+};
+
+} // namespace
+
+
// static
void RenderWidgetHost::RemoveAllBackingStores() {
BackingStoreManager::RemoveAllBackingStores();
@@ -115,7 +152,8 @@ size_t RenderWidgetHost::BackingStoreMemorySize() {
RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
- int routing_id)
+ int routing_id,
+ bool hidden)
: view_(NULL),
renderer_initialized_(false),
hung_renderer_delay_ms_(kHungRendererDelayMs),
@@ -124,11 +162,12 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
routing_id_(routing_id),
surface_id_(0),
is_loading_(false),
- is_hidden_(false),
+ is_hidden_(hidden),
is_fullscreen_(false),
is_accelerated_compositing_active_(false),
repaint_ack_pending_(false),
resize_ack_pending_(false),
+ screen_info_out_of_date_(false),
overdraw_bottom_height_(0.f),
should_auto_resize_(false),
waiting_for_screen_rects_ack_(false),
@@ -175,9 +214,11 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
g_routing_id_widget_map.Get().insert(std::make_pair(
RenderWidgetHostID(process->GetID(), routing_id_), this));
process_->AddRoute(routing_id_, this);
- // Because the widget initializes as is_hidden_ == false,
- // tell the process host that we're alive.
- process_->WidgetRestored();
+
+ // If we're initially visible, tell the process host that we're alive.
+ // Otherwise we'll notify the process host when we are first shown.
+ if (!hidden)
+ process_->WidgetRestored();
accessibility_mode_ =
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
@@ -185,7 +226,8 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
g_created_callbacks.Get().at(i).Run(this);
- input_router_.reset(new ImmediateInputRouter(process, this, routing_id_));
+ input_router_.reset(
+ new ImmediateInputRouter(process_, this, this, routing_id_));
#if defined(USE_AURA)
bool overscroll_enabled = CommandLine::ForCurrentProcess()->
@@ -222,6 +264,7 @@ RenderWidgetHost* RenderWidgetHost::FromID(
RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
int32 process_id,
int32 routing_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
RoutingIDWidgetMap::iterator it = widgets->find(
RenderWidgetHostID(process_id, routing_id));
@@ -229,8 +272,8 @@ RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
}
// static
-std::vector<RenderWidgetHost*> RenderWidgetHost::GetRenderWidgetHosts() {
- std::vector<RenderWidgetHost*> hosts;
+scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
+ RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
it != widgets->end();
@@ -238,28 +281,31 @@ std::vector<RenderWidgetHost*> RenderWidgetHost::GetRenderWidgetHosts() {
RenderWidgetHost* widget = it->second;
if (!widget->IsRenderView()) {
- hosts.push_back(widget);
+ hosts->Add(widget);
continue;
}
// Add only active RenderViewHosts.
RenderViewHost* rvh = RenderViewHost::From(widget);
if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
- hosts.push_back(widget);
+ hosts->Add(widget);
}
- return hosts;
+
+ return scoped_ptr<RenderWidgetHostIterator>(hosts);
}
// static
-std::vector<RenderWidgetHost*> RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
- std::vector<RenderWidgetHost*> hosts;
+scoped_ptr<RenderWidgetHostIterator>
+RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
+ RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
it != widgets->end();
++it) {
- hosts.push_back(it->second);
+ hosts->Add(it->second);
}
- return hosts;
+
+ return scoped_ptr<RenderWidgetHostIterator>(hosts);
}
// static
@@ -358,8 +404,8 @@ void RenderWidgetHostImpl::SendScreenRects() {
}
base::TimeDelta
- RenderWidgetHostImpl::GetSyntheticScrollMessageInterval() const {
- return smooth_scroll_gesture_controller_.GetSyntheticScrollMessageInterval();
+ RenderWidgetHostImpl::GetSyntheticGestureMessageInterval() const {
+ return synthetic_gesture_controller_.GetSyntheticGestureMessageInterval();
}
void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
@@ -430,6 +476,7 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll, OnBeginSmoothScroll)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_BeginPinch, OnBeginPinch)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
@@ -473,12 +520,15 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
- return input_router_->SendInput(msg);
+ return input_router_->SendInput(make_scoped_ptr(msg));
return process_->Send(msg);
}
void RenderWidgetHostImpl::WasHidden() {
+ if (is_hidden_)
+ return;
+
is_hidden_ = true;
// Don't bother reporting hung state when we aren't active.
@@ -499,7 +549,6 @@ void RenderWidgetHostImpl::WasHidden() {
}
void RenderWidgetHostImpl::WasShown() {
- // When we create the widget, it is created as *not* hidden.
if (!is_hidden_)
return;
is_hidden_ = false;
@@ -548,8 +597,10 @@ void RenderWidgetHostImpl::WasShown() {
}
void RenderWidgetHostImpl::WasResized() {
+ // Skip if the |delegate_| has already been detached because
+ // it's web contents is being deleted.
if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
- !renderer_initialized_ || should_auto_resize_) {
+ !renderer_initialized_ || should_auto_resize_ || !delegate_) {
return;
}
@@ -565,7 +616,7 @@ void RenderWidgetHostImpl::WasResized() {
bool size_changed = new_size != last_requested_size_;
bool side_payload_changed =
- !screen_info_.get() ||
+ screen_info_out_of_date_ ||
old_physical_backing_size != physical_backing_size_ ||
was_fullscreen != is_fullscreen_ ||
old_overdraw_bottom_height != overdraw_bottom_height_;
@@ -838,20 +889,20 @@ void RenderWidgetHostImpl::DonePaintingToBackingStore() {
Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
}
-void RenderWidgetHostImpl::ScheduleComposite() {
+bool RenderWidgetHostImpl::ScheduleComposite() {
if (is_hidden_ || !is_accelerated_compositing_active_ ||
- current_size_.IsEmpty()) {
- return;
+ current_size_.IsEmpty() || repaint_ack_pending_ ||
+ resize_ack_pending_ || view_being_painted_) {
+ return false;
}
// Send out a request to the renderer to paint the view if required.
- if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
- repaint_start_time_ = TimeTicks::Now();
- repaint_ack_pending_ = true;
- TRACE_EVENT_ASYNC_BEGIN0(
- "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
- Send(new ViewMsg_Repaint(routing_id_, current_size_));
- }
+ repaint_start_time_ = TimeTicks::Now();
+ repaint_ack_pending_ = true;
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
+ Send(new ViewMsg_Repaint(routing_id_, current_size_));
+ return true;
}
void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
@@ -1010,6 +1061,12 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
const MouseEventWithLatencyInfo& mouse_event) {
TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
"x", mouse_event.event.x, "y", mouse_event.event.y);
+
+ for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
+ if (mouse_event_callbacks_[i].Run(mouse_event.event))
+ return;
+ }
+
input_router_->SendMouseEvent(mouse_event);
}
@@ -1117,15 +1174,35 @@ ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
}
-void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener* listener) {
- keyboard_listeners_.AddObserver(listener);
+void RenderWidgetHostImpl::AddKeyPressEventCallback(
+ const KeyPressEventCallback& callback) {
+ key_press_event_callbacks_.push_back(callback);
+}
+
+void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
+ const KeyPressEventCallback& callback) {
+ for (size_t i = 0; i < key_press_event_callbacks_.size(); ++i) {
+ if (key_press_event_callbacks_[i].Equals(callback)) {
+ key_press_event_callbacks_.erase(
+ key_press_event_callbacks_.begin() + i);
+ return;
+ }
+ }
+}
+
+void RenderWidgetHostImpl::AddMouseEventCallback(
+ const MouseEventCallback& callback) {
+ mouse_event_callbacks_.push_back(callback);
}
-void RenderWidgetHostImpl::RemoveKeyboardListener(
- KeyboardListener* listener) {
- // Ensure that the element is actually an observer.
- DCHECK(keyboard_listeners_.HasObserver(listener));
- keyboard_listeners_.RemoveObserver(listener);
+void RenderWidgetHostImpl::RemoveMouseEventCallback(
+ const MouseEventCallback& callback) {
+ for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
+ if (mouse_event_callbacks_[i].Equals(callback)) {
+ mouse_event_callbacks_.erase(mouse_event_callbacks_.begin() + i);
+ return;
+ }
+ }
}
void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
@@ -1134,6 +1211,7 @@ void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
else
RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
+ screen_info_out_of_date_ = false;
}
const NativeWebKeyboardEvent*
@@ -1150,6 +1228,7 @@ void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
}
void RenderWidgetHostImpl::InvalidateScreenInfo() {
+ screen_info_out_of_date_ = true;
screen_info_.reset();
}
@@ -1200,7 +1279,8 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
waiting_for_screen_rects_ack_ = false;
// Reset to ensure that input routing works with a new renderer.
- input_router_.reset(new ImmediateInputRouter(process_, this, routing_id_));
+ input_router_.reset(
+ new ImmediateInputRouter(process_, this, this, routing_id_));
if (overscroll_controller_)
overscroll_controller_->Reset();
@@ -1262,7 +1342,7 @@ void RenderWidgetHostImpl::ImeSetComposition(
void RenderWidgetHostImpl::ImeConfirmComposition(
const string16& text,
- const ui::Range& replacement_range,
+ const gfx::Range& replacement_range,
bool keep_selection) {
Send(new ViewMsg_ImeConfirmComposition(
GetRoutingID(), text, replacement_range, keep_selection));
@@ -1482,7 +1562,9 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
ack.gl_frame_data = frame->gl_frame_data.Pass();
ack.gl_frame_data->sync_point = 0;
} else if (frame->delegated_frame_data) {
- ack.resources.swap(frame->delegated_frame_data->resource_list);
+ cc::TransferableResource::ReturnResources(
+ frame->delegated_frame_data->resource_list,
+ &ack.resources);
} else if (frame->software_frame_data) {
ack.last_software_frame_id = frame->software_frame_data->id;
}
@@ -1665,7 +1747,14 @@ void RenderWidgetHostImpl::OnBeginSmoothScroll(
const ViewHostMsg_BeginSmoothScroll_Params& params) {
if (!view_)
return;
- smooth_scroll_gesture_controller_.BeginSmoothScroll(view_, params);
+ synthetic_gesture_controller_.BeginSmoothScroll(view_, params);
+}
+
+void RenderWidgetHostImpl::OnBeginPinch(
+ const ViewHostMsg_BeginPinch_Params& params) {
+ if (!view_)
+ return;
+ synthetic_gesture_controller_.BeginPinch(view_, params);
}
void RenderWidgetHostImpl::OnFocus() {
@@ -1689,15 +1778,15 @@ void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
void RenderWidgetHostImpl::OnTextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (view_)
- view_->TextInputTypeChanged(type, can_compose_inline, input_mode);
+ view_->TextInputTypeChanged(type, input_mode, can_compose_inline);
}
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
if (view_)
view_->ImeCompositionRangeChanged(range, character_bounds);
@@ -1879,10 +1968,8 @@ bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
return false;
- ObserverList<KeyboardListener>::Iterator it(keyboard_listeners_);
- KeyboardListener* listener;
- while ((listener = it.GetNext()) != NULL) {
- if (listener->HandleKeyPressEvent(event))
+ for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
+ if (key_press_event_callbacks_[i].Run(event))
return true;
}
@@ -2067,6 +2154,12 @@ bool RenderWidgetHostImpl::OnSendGestureEventImmediately(
return !IgnoreInputEvents();
}
+void RenderWidgetHostImpl::SetNeedsFlush() {
+}
+
+void RenderWidgetHostImpl::DidFlush() {
+}
+
void RenderWidgetHostImpl::OnKeyboardEventAck(
const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) {
@@ -2118,13 +2211,13 @@ void RenderWidgetHostImpl::OnTouchEventAck(
view_->ProcessAckedTouchEvent(event, ack_result);
}
-void RenderWidgetHostImpl::OnUnexpectedEventAck(bool bad_message) {
- if (bad_message) {
+void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
+ if (type == BAD_ACK_MESSAGE) {
RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
process_->ReceivedBadMessage();
+ } else if (type == UNEXPECTED_EVENT_TYPE) {
+ suppress_next_char_events_ = false;
}
-
- suppress_next_char_events_ = false;
}
const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
@@ -2144,10 +2237,6 @@ bool RenderWidgetHostImpl::ShouldForwardGestureEvent(
return input_router_->ShouldForwardGestureEvent(gesture_event);
}
-bool RenderWidgetHostImpl::HasQueuedGestureEvents() const {
- return input_router_->HasQueuedGestureEvents();
-}
-
void RenderWidgetHostImpl::StartUserGesture() {
OnUserGesture();
}
@@ -2331,6 +2420,19 @@ void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
route_id, output_surface_id, ack));
}
+// static
+void RenderWidgetHostImpl::SendReclaimCompositorResources(
+ int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack) {
+ RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
+ if (!host)
+ return;
+ host->Send(
+ new ViewMsg_ReclaimCompositorResources(route_id, output_surface_id, ack));
+}
+
void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
if (!is_threaded_compositing_enabled_)
Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h
index 362c6d7f793..613177c9a81 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -23,8 +23,9 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "content/browser/renderer_host/input/input_ack_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
+#include "content/browser/renderer_host/synthetic_gesture_controller.h"
#include "content/common/browser_rendering_stats.h"
#include "content/common/view_message_enums.h"
#include "content/port/browser/event_with_latency_info.h"
@@ -34,7 +35,7 @@
#include "ipc/ipc_listener.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
-#include "ui/base/latency_info.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
class WebCursor;
@@ -53,9 +54,12 @@ class CompositorFrame;
class CompositorFrameAck;
}
+namespace gfx {
+class Range;
+}
+
namespace ui {
class KeyEvent;
-class Range;
}
namespace WebKit {
@@ -78,13 +82,14 @@ class MockRenderWidgetHost;
class OverscrollController;
class RenderWidgetHostDelegate;
class RenderWidgetHostViewPort;
-class SmoothScrollGestureController;
+class SyntheticGestureController;
struct EditCommand;
// This implements the RenderWidgetHost interface that is exposed to
// embedders of content, and adds things only visible to content.
class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
public InputRouterClient,
+ public InputAckHandler,
public IPC::Listener {
public:
// routing_id can be MSG_ROUTING_NONE, in which case the next available
@@ -93,7 +98,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// |delegate| goes away.
RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
- int routing_id);
+ int routing_id,
+ bool hidden);
virtual ~RenderWidgetHostImpl();
// Similar to RenderWidgetHost::FromID, but returning the Impl object.
@@ -102,14 +108,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Returns all RenderWidgetHosts including swapped out ones for
// internal use. The public interface
// RendgerWidgetHost::GetRenderWidgetHosts only returns active ones.
- // Keep in mind that there may be dependencies between these
- // widgets. If a caller indirectly causes one of the widgets to be
- // deleted while iterating over the list, the deleted widget will
- // stay in the list and possibly causes a use-after-free. Take care
- // to avoid deleting widgets as you iterate (e.g., see
- // http://crbug.com/259859). TODO(nasko): Improve this interface to
- // better prevent UaFs.
- static std::vector<RenderWidgetHost*> GetAllRenderWidgetHosts();
+ static scoped_ptr<RenderWidgetHostIterator> GetAllRenderWidgetHosts();
// Use RenderWidgetHostImpl::From(rwh) to downcast a
// RenderWidgetHost to a RenderWidgetHostImpl. Internally, this
@@ -172,8 +171,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE;
virtual void Stop() OVERRIDE;
virtual void WasResized() OVERRIDE;
- virtual void AddKeyboardListener(KeyboardListener* listener) OVERRIDE;
- virtual void RemoveKeyboardListener(KeyboardListener* listener) OVERRIDE;
+ virtual void AddKeyPressEventCallback(
+ const KeyPressEventCallback& callback) OVERRIDE;
+ virtual void RemoveKeyPressEventCallback(
+ const KeyPressEventCallback& callback) OVERRIDE;
+ virtual void AddMouseEventCallback(
+ const MouseEventCallback& callback) OVERRIDE;
+ virtual void RemoveMouseEventCallback(
+ const MouseEventCallback& callback) OVERRIDE;
virtual void GetWebScreenInfo(WebKit::WebScreenInfo* result) OVERRIDE;
virtual void GetSnapshotFromRenderer(
const gfx::Rect& src_subrect,
@@ -199,7 +204,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Called when a renderer object already been created for this host, and we
// just need to be attached to it. Used for window.open, <select> dropdown
// menus, and other times when the renderer initiates creating an object.
- void Init();
+ virtual void Init();
// Tells the renderer to die and then calls Destroy().
virtual void Shutdown();
@@ -267,9 +272,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void DonePaintingToBackingStore();
// GPU accelerated version of GetBackingStore function. This will
- // trigger a re-composite to the view. If a resize is pending, it will
- // block briefly waiting for an ack from the renderer.
- void ScheduleComposite();
+ // trigger a re-composite to the view. It may fail if a resize is pending, or
+ // if a composite has already been requested and not acked yet.
+ bool ScheduleComposite();
// Starts a hang monitor timeout. If there's already a hang monitor timeout
// the new one will only fire if it has a shorter delay than the time
@@ -335,7 +340,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// * when it receives a "commit" signal of GtkIMContext (on Linux);
// * when insertText of NSTextInput is called (on Mac).
void ImeConfirmComposition(const string16& text,
- const ui::Range& replacement_range,
+ const gfx::Range& replacement_range,
bool keep_selection);
// Cancels an ongoing composition.
@@ -365,7 +370,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
bool ShouldForwardTouchEvent() const;
bool ShouldForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) const;
- bool HasQueuedGestureEvents() const;
bool has_touch_handler() const { return has_touch_handler_; }
@@ -463,6 +467,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
int renderer_host_id,
const cc::CompositorFrameAck& ack);
+ // Called by the view to return resources to the compositor.
+ static void SendReclaimCompositorResources(int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack);
+
// Called by the view in response to AcceleratedSurfaceBuffersSwapped for
// platforms that support deferred GPU process descheduling. This does
// nothing if the compositor thread is enabled.
@@ -503,7 +513,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
return overscroll_controller_.get();
}
- base::TimeDelta GetSyntheticScrollMessageInterval() const;
+ base::TimeDelta GetSyntheticGestureMessageInterval() const;
// Sets whether the overscroll controller should be enabled for this page.
void SetOverscrollControllerEnabled(bool enabled);
@@ -648,15 +658,17 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void OnUpdateIsDelayed();
void OnBeginSmoothScroll(
const ViewHostMsg_BeginSmoothScroll_Params& params);
+ void OnBeginPinch(
+ const ViewHostMsg_BeginPinch_Params& params);
virtual void OnFocus();
virtual void OnBlur();
void OnSetCursor(const WebCursor& cursor);
void OnTextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode);
+ ui::TextInputMode input_mode,
+ bool can_compose_inline);
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void OnImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds);
#endif
void OnImeCancelComposition();
@@ -729,6 +741,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
virtual bool OnSendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual void SetNeedsFlush() OVERRIDE;
+ virtual void DidFlush() OVERRIDE;
+
+ // InputAckHandler
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
@@ -737,7 +753,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
InputEventAckState ack_result) OVERRIDE;
virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnUnexpectedEventAck(bool bad_message) OVERRIDE;
+ virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
void SimulateTouchGestureWithMouse(const WebKit::WebMouseEvent& mouse_event);
@@ -745,7 +761,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// which may get in recursive loops).
void DelayedAutoResized();
-
// Our delegate, which wants to know mainly about keyboard events.
// It will remain non-NULL until DetachDelegate() is called.
RenderWidgetHostDelegate* delegate_;
@@ -821,7 +836,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
AccessibilityMode accessibility_mode_;
// Keyboard event listeners.
- ObserverList<KeyboardListener> keyboard_listeners_;
+ std::vector<KeyPressEventCallback> key_press_event_callbacks_;
+
+ // Mouse event callbacks.
+ std::vector<MouseEventCallback> mouse_event_callbacks_;
// If true, then we should repaint when restoring even if we have a
// backingstore. This flag is set to true if we receive a paint message
@@ -899,7 +917,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
- SmoothScrollGestureController smooth_scroll_gesture_controller_;
+ SyntheticGestureController synthetic_gesture_controller_;
// Receives and handles all input events.
scoped_ptr<InputRouter> input_router_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
index 960ce5eb92a..21c368ab488 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
+#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/timer/timer.h"
@@ -28,7 +29,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/screen.h"
@@ -40,7 +41,7 @@
#if defined(OS_WIN) || defined(USE_AURA)
#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
#endif
using base::TimeDelta;
@@ -104,30 +105,6 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
DISALLOW_COPY_AND_ASSIGN(TestOverscrollDelegate);
};
-// MockKeyboardListener --------------------------------------------------------
-class MockKeyboardListener : public KeyboardListener {
- public:
- MockKeyboardListener()
- : handle_key_press_event_(false) {
- }
- virtual ~MockKeyboardListener() {}
-
- // KeyboardListener:
- virtual bool HandleKeyPressEvent(
- const NativeWebKeyboardEvent& event) OVERRIDE {
- return handle_key_press_event_;
- }
-
- void set_handle_key_press_event(bool handle) {
- handle_key_press_event_ = handle;
- }
-
- private:
- bool handle_key_press_event_;
-
- DISALLOW_COPY_AND_ASSIGN(MockKeyboardListener);
-};
-
// MockInputRouter -------------------------------------------------------------
class MockInputRouter : public InputRouter {
@@ -145,12 +122,11 @@ class MockInputRouter : public InputRouter {
virtual ~MockInputRouter() {}
// InputRouter
- virtual bool SendInput(IPC::Message* message) OVERRIDE {
+ virtual void Flush() OVERRIDE {
+ flush_called_ = true;
+ }
+ virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE {
send_event_called_ = true;
-
- // SendInput takes ownership of message
- delete message;
-
return true;
}
virtual void SendMouseEvent(
@@ -195,7 +171,6 @@ class MockInputRouter : public InputRouter {
const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE {
return true;
}
- virtual bool HasQueuedGestureEvents() const OVERRIDE { return true; }
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
@@ -203,6 +178,7 @@ class MockInputRouter : public InputRouter {
return false;
}
+ bool flush_called_;
bool send_event_called_;
bool sent_mouse_event_;
bool sent_wheel_event_;
@@ -225,7 +201,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id),
+ : RenderWidgetHostImpl(delegate, process, routing_id, false),
unresponsive_timer_fired_(false) {
immediate_input_router_ =
static_cast<ImmediateInputRouter*>(input_router_.get());
@@ -628,11 +604,21 @@ class MockPaintingObserver : public NotificationObserver {
class RenderWidgetHostTest : public testing::Test {
public:
- RenderWidgetHostTest() : process_(NULL) {
+ RenderWidgetHostTest()
+ : process_(NULL),
+ handle_key_press_event_(false),
+ handle_mouse_event_(false) {
}
virtual ~RenderWidgetHostTest() {
}
+ bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
+ return handle_key_press_event_;
+ }
+ bool MouseEventCallback(const WebKit::WebMouseEvent& /* event */) {
+ return handle_mouse_event_;
+ }
+
protected:
// testing::Test
virtual void SetUp() {
@@ -835,6 +821,8 @@ class RenderWidgetHostTest : public testing::Test {
scoped_ptr<MockRenderWidgetHost> host_;
scoped_ptr<TestView> view_;
scoped_ptr<gfx::Screen> screen_;
+ bool handle_key_press_event_;
+ bool handle_mouse_event_;
private:
WebTouchEvent touch_event_;
@@ -857,13 +845,12 @@ class RenderWidgetHostWithSourceTest
// -----------------------------------------------------------------------------
TEST_F(RenderWidgetHostTest, Resize) {
- // The initial bounds is the empty rect, but the screen info hasn't been sent
- // yet, so setting it to the same thing should send the resize message.
+ // The initial bounds is the empty rect, and the screen info hasn't been sent
+ // yet, so setting it to the same thing shouldn't send the resize message.
view_->set_bounds(gfx::Rect());
host_->WasResized();
EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(), host_->last_requested_size_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
// Setting the bounds to a "real" rect should send out the notification.
// but should not expect ack for empty physical backing size.
@@ -1397,6 +1384,7 @@ TEST_F(RenderWidgetHostTest, WheelScrollEventOverscrolls) {
SimulateMouseMove(5, 10, 0);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
// Tests that if some scroll events are consumed towards the start, then
@@ -1618,10 +1606,10 @@ TEST_F(RenderWidgetHostTest, ScrollEventsOverscrollWithZeroFling) {
// Send a fling start, but with a small velocity, so that the overscroll is
// aborted. The fling should proceed to the renderer, through the gesture
// event filter.
- SimulateGestureFlingStartEvent(0.f, 0.f, WebGestureEvent::Touchpad);
+ SimulateGestureFlingStartEvent(10.f, 0.f, WebGestureEvent::Touchpad);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
- EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
// Tests that a fling in the opposite direction of the overscroll cancels the
@@ -1646,11 +1634,13 @@ TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
SendInputEventACK(WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
@@ -1670,9 +1660,12 @@ TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_WEST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_WEST, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
+
SimulateGestureFlingStartEvent(100, 0, WebGestureEvent::Touchscreen);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, process_->sink().message_count());
}
}
@@ -1750,11 +1743,14 @@ TEST_F(RenderWidgetHostTest, GestureScrollConsumedHorizontal) {
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
+ process_->sink().ClearMessages();
// Send another gesture event and ACK as not being processed. This should
// not initiate overscroll because the beginning of the scroll event did
- // scroll some content on the page.
+ // scroll some content on the page. Since there was no overscroll, the event
+ // should reach the renderer.
SimulateGestureScrollUpdateEvent(55, 0, 0);
+ EXPECT_EQ(1U, process_->sink().message_count());
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
@@ -2301,12 +2297,15 @@ TEST_F(RenderWidgetHostTest, OverscrollMouseMoveCompletion) {
// Overscroll gesture is in progress. Send a mouse-move now. This should
// complete the gesture (because the amount overscrolled is above the
- // threshold), and consume the event.
+ // threshold).
SimulateMouseMove(5, 10, 0);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
@@ -2499,32 +2498,30 @@ TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
TEST_F(RenderWidgetHostTest, KeyboardListenerIgnoresEvent) {
host_->SetupForInputRouterTest();
-
- scoped_ptr<MockKeyboardListener> keyboard_listener_(new MockKeyboardListener);
- host_->AddKeyboardListener(keyboard_listener_.get());
-
- keyboard_listener_->set_handle_key_press_event(false);
+ host_->AddKeyPressEventCallback(
+ base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
+ base::Unretained(this)));
+ handle_key_press_event_ = false;
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
-
- host_->RemoveKeyboardListener(keyboard_listener_.get());
}
TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) {
host_->SetupForInputRouterTest();
- scoped_ptr<MockKeyboardListener> keyboard_listener_(new MockKeyboardListener);
- host_->AddKeyboardListener(keyboard_listener_.get());
+ host_->AddKeyPressEventCallback(
+ base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
+ base::Unretained(this)));
- // KeyboardListener handles the first event
- keyboard_listener_->set_handle_key_press_event(true);
+ // The callback handles the first event
+ handle_key_press_event_ = true;
SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
// Following Char events should be suppressed
- keyboard_listener_->set_handle_key_press_event(false);
+ handle_key_press_event_ = false;
SimulateKeyboardEvent(WebInputEvent::Char);
EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
SimulateKeyboardEvent(WebInputEvent::Char);
@@ -2537,8 +2534,24 @@ TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) {
host_->mock_input_router()->sent_keyboard_event_ = false;
SimulateKeyboardEvent(WebInputEvent::Char);
EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
+}
+
+TEST_F(RenderWidgetHostTest, MouseEventCallbackCanHandleEvent) {
+ host_->SetupForInputRouterTest();
+
+ host_->AddMouseEventCallback(
+ base::Bind(&RenderWidgetHostTest::MouseEventCallback,
+ base::Unretained(this)));
+
+ handle_mouse_event_ = true;
+ SimulateMouseEvent(WebInputEvent::MouseDown);
+
+ EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_);
+
+ handle_mouse_event_ = false;
+ SimulateMouseEvent(WebInputEvent::MouseDown);
- host_->RemoveKeyboardListener(keyboard_listener_.get());
+ EXPECT_TRUE(host_->mock_input_router()->sent_mouse_event_);
}
TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
index 8e885407e5c..3b94566748f 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -6,8 +6,9 @@
#include <android/bitmap.h>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -20,6 +21,7 @@
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "cc/resources/single_release_callback.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/android/content_view_core_impl.h"
@@ -28,10 +30,10 @@
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/generic_touch_gesture_android.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_android.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
@@ -51,6 +53,7 @@ namespace content {
namespace {
const int kUndefinedOutputSurfaceId = -1;
+const int kMinimumPointerDistance = 50;
void InsertSyncPointAndAckForGpu(
int gpu_host_id, int route_id, const std::string& return_mailbox) {
@@ -88,12 +91,12 @@ void SendImeEventAck(RenderWidgetHostImpl* host) {
void CopyFromCompositingSurfaceFinished(
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
scoped_ptr<SkBitmap> bitmap,
scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
bitmap_pixels_lock.reset();
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result, *bitmap);
}
@@ -196,7 +199,7 @@ RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewAndroid::WasShown() {
- if (!host_->is_hidden())
+ if (!host_ || !host_->is_hidden())
return;
host_->WasShown();
@@ -205,7 +208,7 @@ void RenderWidgetHostViewAndroid::WasShown() {
void RenderWidgetHostViewAndroid::WasHidden() {
RunAckCallbacks();
- if (host_->is_hidden())
+ if (!host_ || host_->is_hidden())
return;
// Inform the renderer that we are being hidden so it can reduce its resource
@@ -353,6 +356,8 @@ void RenderWidgetHostViewAndroid::Show() {
are_layers_attached_ = true;
AttachLayers();
+
+ WasShown();
}
void RenderWidgetHostViewAndroid::Hide() {
@@ -361,6 +366,8 @@ void RenderWidgetHostViewAndroid::Hide() {
are_layers_attached_ = false;
RemoveLayers();
+
+ WasHidden();
}
bool RenderWidgetHostViewAndroid::IsShowing() {
@@ -406,8 +413,8 @@ void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewAndroid::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
// Unused on Android, which uses OnTextInputChanged instead.
}
@@ -420,9 +427,9 @@ void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
// If an acknowledgement is required for this event, regardless of how we exit
// from this method, we must acknowledge that we processed the input state
// change.
- base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
- if (!params.require_ack)
- ack_caller.Release();
+ base::ScopedClosureRunner ack_caller;
+ if (params.require_ack)
+ ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
if (!IsShowing())
return;
@@ -510,7 +517,7 @@ void RenderWidgetHostViewAndroid::SetTooltipText(
void RenderWidgetHostViewAndroid::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
if (text.empty() || range.is_empty() || !content_view_core_)
@@ -606,14 +613,28 @@ void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
}
-SmoothScrollGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
+SyntheticGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) {
- return new TouchSmoothScrollGestureAndroid(
- pixels_to_scroll,
+ return new GenericTouchGestureAndroid(
+ GetRenderWidgetHost(),
+ content_view_core_->CreateOnePointTouchGesture(
+ mouse_event_x, mouse_event_y,
+ 0, scroll_down ? -pixels_to_scroll : pixels_to_scroll));
+}
+
+SyntheticGesture* RenderWidgetHostViewAndroid::CreatePinchGesture(
+ bool zoom_in, int pixels_to_move, int anchor_x,
+ int anchor_y) {
+ int distance_between_pointers = zoom_in ?
+ kMinimumPointerDistance : (kMinimumPointerDistance + pixels_to_move);
+ return new GenericTouchGestureAndroid(
GetRenderWidgetHost(),
- content_view_core_->CreateSmoothScroller(
- scroll_down, mouse_event_x, mouse_event_y));
+ content_view_core_->CreateTwoPointTouchGesture(
+ anchor_x, anchor_y - distance_between_pointers / 2,
+ 0, (zoom_in ? -pixels_to_move : pixels_to_move) / 2,
+ anchor_x, anchor_y + distance_between_pointers / 2,
+ 0, (zoom_in ? pixels_to_move : -pixels_to_move) / 2));
}
void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
@@ -828,7 +849,7 @@ void RenderWidgetHostViewAndroid::CreateOverscrollEffectIfNecessary() {
if (!overscroll_effect_enabled_ || overscroll_effect_)
return;
- overscroll_effect_ = OverscrollGlow::Create(true);
+ overscroll_effect_ = OverscrollGlow::Create(true, content_size_in_layer_);
// Prevent future creation attempts on failure.
if (!overscroll_effect_)
@@ -950,8 +971,8 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
-void RenderWidgetHostViewAndroid::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewAndroid::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!host_ ||
host_->accessibility_mode() != AccessibilityModeComplete ||
!content_view_core_) {
@@ -965,7 +986,7 @@ void RenderWidgetHostViewAndroid::OnAccessibilityNotifications(
BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
this));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
void RenderWidgetHostViewAndroid::SetAccessibilityFocus(int acc_obj_id) {
@@ -1183,6 +1204,7 @@ WebKit::WebGraphicsContext3D* RenderWidgetHostViewAndroid::Context3d() {
bool RenderWidgetHostViewAndroid::PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback,
bool use_shared_memory) {
return false;
}
@@ -1223,23 +1245,25 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
new SkAutoLockPixels(*bitmap));
uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ cc::TextureMailbox texture_mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+ if (!texture_mailbox.IsTexture())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
result->size(),
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
- texture_mailbox->callback(),
+ base::Passed(&release_callback),
base::Passed(&bitmap),
base::Passed(&bitmap_pixels_lock)));
}
@@ -1264,7 +1288,7 @@ void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult(
DCHECK_EQ(source->width(), dst_size_in_pixel.width());
DCHECK_EQ(source->height(), dst_size_in_pixel.height());
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
callback.Run(true, *source);
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index d8ea83da7ce..6f248076e97 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
@@ -36,6 +36,7 @@ namespace cc {
class CopyOutputResult;
class DelegatedRendererLayer;
class Layer;
+class SingleReleaseCallback;
class TextureLayer;
}
@@ -98,8 +99,8 @@ class RenderWidgetHostViewAndroid
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -112,7 +113,7 @@ class RenderWidgetHostViewAndroid
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -152,8 +153,8 @@ class RenderWidgetHostViewAndroid
const WebKit::WebInputEvent& input_event) OVERRIDE;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -165,9 +166,12 @@ class RenderWidgetHostViewAndroid
gfx::Vector2dF current_fling_velocity) OVERRIDE;
virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
const SkBitmap& zoomed_bitmap) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) OVERRIDE;
+ virtual SyntheticGesture* CreatePinchGesture(
+ bool zoom_in, int pixels_to_move, int anchor_x,
+ int anchor_y) OVERRIDE;
// Implementation of BrowserAccessibilityDelegate:
virtual void SetAccessibilityFocus(int acc_obj_id) OVERRIDE;
@@ -184,8 +188,10 @@ class RenderWidgetHostViewAndroid
// cc::TextureLayerClient implementation.
virtual unsigned PrepareTexture() OVERRIDE;
virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
- virtual bool PrepareTextureMailbox(cc::TextureMailbox* mailbox,
- bool use_shared_memory) OVERRIDE;
+ virtual bool PrepareTextureMailbox(
+ cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback,
+ bool use_shared_memory) OVERRIDE;
// cc::DelegatedRendererLayerClient implementation.
virtual void DidCommitFrameData() OVERRIDE;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
index 33ee9524e73..2eb34b98d38 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -4,8 +4,9 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
@@ -16,8 +17,11 @@
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/resources/texture_mailbox.h"
+#include "cc/trees/layer_tree_settings.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/aura/compositor_resize_lock.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/backing_store_aura.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/overscroll_controller.h"
@@ -57,13 +61,13 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect_conversions.h"
@@ -77,6 +81,7 @@
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "ui/base/win/hidden_window.h"
#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/win/dpi.h"
#endif
using gfx::RectToSkIRect;
@@ -100,10 +105,10 @@ class MemoryHolder : public base::RefCounted<MemoryHolder> {
frame_size_(frame_size),
callback_(callback) {}
- cc::TextureMailbox GetMailbox() {
- return cc::TextureMailbox(
- shared_memory_.get(),
- frame_size_,
+ void GetMailbox(cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* release_callback) {
+ *mailbox = cc::TextureMailbox(shared_memory_.get(), frame_size_);
+ *release_callback = cc::SingleReleaseCallback::Create(
base::Bind(ReleaseMailbox, make_scoped_refptr(this)));
}
@@ -118,6 +123,11 @@ class MemoryHolder : public base::RefCounted<MemoryHolder> {
namespace {
+void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
+ unsigned sync_point, bool lost_resource) {
+ // NOTE: shared_memory will get released when we go out of scope.
+}
+
// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
// the border of the view, in order to get valid movement information. However,
// forcing the cursor back to the center of the view after each mouse move
@@ -567,73 +577,6 @@ class RenderWidgetHostViewAura::TransientWindowObserver
#endif
-class RenderWidgetHostViewAura::ResizeLock {
- public:
- ResizeLock(aura::RootWindow* root_window,
- const gfx::Size new_size,
- bool defer_compositor_lock)
- : root_window_(root_window),
- new_size_(new_size),
- compositor_lock_(defer_compositor_lock ?
- NULL :
- root_window_->compositor()->GetCompositorLock()),
- weak_ptr_factory_(this),
- defer_compositor_lock_(defer_compositor_lock) {
- TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- root_window_->HoldPointerMoves();
-
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderWidgetHostViewAura::ResizeLock::CancelLock,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs));
- }
-
- ~ResizeLock() {
- CancelLock();
- TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this,
- "width", new_size_.width(),
- "height", new_size_.height());
- }
-
- void UnlockCompositor() {
- defer_compositor_lock_ = false;
- compositor_lock_ = NULL;
- }
-
- void CancelLock() {
- if (!root_window_)
- return;
- UnlockCompositor();
- root_window_->ReleasePointerMoves();
- root_window_ = NULL;
- }
-
- const gfx::Size& expected_size() const {
- return new_size_;
- }
-
- bool GrabDeferredLock() {
- if (root_window_ && defer_compositor_lock_) {
- compositor_lock_ = root_window_->compositor()->GetCompositorLock();
- defer_compositor_lock_ = false;
- return true;
- }
- return false;
- }
-
- private:
- aura::RootWindow* root_window_;
- gfx::Size new_size_;
- scoped_refptr<ui::CompositorLock> compositor_lock_;
- base::WeakPtrFactory<ResizeLock> weak_ptr_factory_;
- bool defer_compositor_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(ResizeLock);
-};
-
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, public:
@@ -646,8 +589,11 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
popup_child_host_view_(NULL),
is_loading_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+ text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
can_compose_inline_(true),
has_composition_text_(false),
+ last_output_surface_id_(0),
+ skipped_frames_(false),
last_swapped_surface_scale_factor_(1.f),
paint_canvas_(NULL),
synthetic_move_sent_(false),
@@ -746,18 +692,26 @@ RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewAura::WasShown() {
+ DCHECK(host_);
if (!host_->is_hidden())
return;
host_->WasShown();
+ if (framebuffer_holder_)
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, true);
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(window_->GetRootWindow());
- if (cursor_client)
- NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+ aura::RootWindow* root = window_->GetRootWindow();
+ if (root) {
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root);
+ if (cursor_client)
+ NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+ }
if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
!released_front_lock_.get()) {
- released_front_lock_ = GetCompositor()->GetCompositorLock();
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor)
+ released_front_lock_ = compositor->GetCompositorLock();
}
#if defined(OS_WIN)
@@ -768,9 +722,11 @@ void RenderWidgetHostViewAura::WasShown() {
}
void RenderWidgetHostViewAura::WasHidden() {
- if (host_->is_hidden())
+ if (!host_ || host_->is_hidden())
return;
host_->WasHidden();
+ if (framebuffer_holder_)
+ FrameMemoryManager::GetInstance()->SetFrameVisibility(this, false);
released_front_lock_ = NULL;
@@ -803,39 +759,69 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
}
void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
- gfx::Size desired_size = window_->bounds().size();
- if (!host_->should_auto_resize() &&
- !resize_lock_.get() &&
- desired_size != current_frame_size_ &&
- host_->is_accelerated_compositing_active()) {
- aura::RootWindow* root_window = window_->GetRootWindow();
- ui::Compositor* compositor = root_window ?
- root_window->compositor() : NULL;
- if (root_window && compositor) {
- // Listen to changes in the compositor lock state.
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
-// On Windows while resizing, the the resize locks makes us mis-paint a white
-// vertical strip (including the non-client area) if the content composition is
-// lagging the UI composition. So here we disable the throttling so that the UI
-// bits can draw ahead of the content thereby reducing the amount of whiteout.
-// Because this causes the content to be drawn at wrong sizes while resizing
-// we compensate by blocking the UI thread in Compositor::Draw() by issuing a
-// FinishAllRendering() if we are resizing.
-#if !defined (OS_WIN)
- bool defer_compositor_lock =
- can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT;
-
- if (can_lock_compositor_ == YES)
- can_lock_compositor_ = YES_DID_LOCK;
-
- resize_lock_.reset(new ResizeLock(root_window, desired_size,
- defer_compositor_lock));
+ if (!ShouldCreateResizeLock())
+ return;
+ DCHECK(window_->GetRootWindow());
+ DCHECK(window_->GetRootWindow()->compositor());
+
+ // Listen to changes in the compositor lock state.
+ ui::Compositor* compositor = window_->GetRootWindow()->compositor();
+ if (!compositor->HasObserver(this))
+ compositor->AddObserver(this);
+
+ bool defer_compositor_lock =
+ can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
+ can_lock_compositor_ == NO_PENDING_COMMIT;
+
+ if (can_lock_compositor_ == YES)
+ can_lock_compositor_ = YES_DID_LOCK;
+
+ resize_lock_ = CreateResizeLock(defer_compositor_lock);
+}
+
+bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
+ // On Windows while resizing, the the resize locks makes us mis-paint a white
+ // vertical strip (including the non-client area) if the content composition
+ // is lagging the UI composition. So here we disable the throttling so that
+ // the UI bits can draw ahead of the content thereby reducing the amount of
+ // whiteout. Because this causes the content to be drawn at wrong sizes while
+ // resizing we compensate by blocking the UI thread in Compositor::Draw() by
+ // issuing a FinishAllRendering() if we are resizing.
+#if defined (OS_WIN)
+ return false;
#endif
- }
- }
+
+ if (resize_lock_)
+ return false;
+
+ if (host_->should_auto_resize())
+ return false;
+ if (!host_->is_accelerated_compositing_active())
+ return false;
+
+ gfx::Size desired_size = window_->bounds().size();
+ if (desired_size == current_frame_size_)
+ return false;
+
+ aura::RootWindow* root_window = window_->GetRootWindow();
+ if (!root_window)
+ return false;
+
+ ui::Compositor* compositor = root_window->compositor();
+ if (!compositor)
+ return false;
+
+ return true;
+}
+
+scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
+ bool defer_compositor_lock) {
+ gfx::Size desired_size = window_->bounds().size();
+ return scoped_ptr<ResizeLock>(new CompositorResizeLock(
+ window_->GetRootWindow(),
+ desired_size,
+ defer_compositor_lock,
+ base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
}
gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
@@ -983,10 +969,12 @@ bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewAura::Show() {
window_->Show();
+ WasShown();
}
void RenderWidgetHostViewAura::Hide() {
window_->Hide();
+ WasHidden();
}
bool RenderWidgetHostViewAura::IsShowing() {
@@ -1010,18 +998,6 @@ void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
-RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (!manager)
- return NULL;
-
- return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
- child_id);
-}
-#endif // defined(OS_WIN)
-
void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
current_cursor_ = cursor;
const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
@@ -1039,11 +1015,13 @@ void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewAura::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type ||
+ text_input_mode_ != input_mode ||
can_compose_inline_ != can_compose_inline) {
text_input_type_ = type;
+ text_input_mode_ = input_mode;
can_compose_inline_ = can_compose_inline;
if (GetInputMethod())
GetInputMethod()->OnTextInputTypeChanged(this);
@@ -1059,7 +1037,7 @@ void RenderWidgetHostViewAura::ImeCancelComposition() {
}
void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
composition_character_bounds_ = character_bounds;
}
@@ -1144,7 +1122,7 @@ void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
#if defined(USE_X11) && !defined(OS_CHROMEOS)
@@ -1308,9 +1286,14 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
current_frame_size_ = ConvertSizeToDIP(
current_surface_->device_scale_factor(), current_surface_->size());
CheckResizeLock();
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
} else if (is_compositing_active && framebuffer_holder_) {
- cc::TextureMailbox mailbox = framebuffer_holder_->GetMailbox();
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ framebuffer_holder_->GetMailbox(&mailbox, &callback);
window_->layer()->SetTextureMailbox(mailbox,
+ callback.Pass(),
last_swapped_surface_scale_factor_);
current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
mailbox.shared_memory_size());
@@ -1319,6 +1302,8 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
window_->layer()->SetExternalTexture(NULL);
resize_lock_.reset();
host_->WasResized();
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
}
}
@@ -1440,20 +1425,58 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
scoped_ptr<cc::DelegatedFrameData> frame_data,
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info) {
+ gfx::Size frame_size;
gfx::Size frame_size_in_dip;
+ gfx::Rect damage_rect;
+ gfx::Rect damage_rect_in_dip;
+
if (!frame_data->render_pass_list.empty()) {
- frame_size_in_dip = gfx::ToFlooredSize(gfx::ScaleSize(
- frame_data->render_pass_list.back()->output_rect.size(),
- 1.f/frame_device_scale_factor));
+ cc::RenderPass* root_pass = frame_data->render_pass_list.back();
+
+ frame_size = root_pass->output_rect.size();
+ frame_size_in_dip = ConvertSizeToDIP(frame_device_scale_factor, frame_size);
+
+ damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
+ damage_rect.Intersect(gfx::Rect(frame_size));
+ damage_rect_in_dip = ConvertRectToDIP(frame_device_scale_factor,
+ damage_rect);
}
+
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
+
if (ShouldSkipFrame(frame_size_in_dip)) {
cc::CompositorFrameAck ack;
- ack.resources.swap(frame_data->resource_list);
+ cc::TransferableResource::ReturnResources(frame_data->resource_list,
+ &ack.resources);
RenderWidgetHostImpl::SendSwapCompositorFrameAck(
host_->GetRoutingID(), output_surface_id,
host_->GetProcess()->GetID(), ack);
+ skipped_frames_ = true;
return;
}
+
+ if (skipped_frames_) {
+ skipped_frames_ = false;
+ damage_rect = gfx::Rect(frame_size);
+ damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
+
+ // Give the same damage rect to the compositor.
+ cc::RenderPass* root_pass = frame_data->render_pass_list.back();
+ root_pass->damage_rect = damage_rect;
+ }
+
+ if (output_surface_id != last_output_surface_id_) {
+ // Resource ids are scoped by the output surface.
+ // If the originating output surface doesn't match the last one, it
+ // indicates the renderer's output surface may have been recreated, in which
+ // case we should recreate the DelegatedRendererLayer, to avoid matching
+ // resources from the old one with resources from the new one which would
+ // have the same id.
+ window_->layer()->SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData>(),
+ frame_size_in_dip);
+ last_output_surface_id_ = output_surface_id;
+ }
window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
released_front_lock_ = NULL;
current_frame_size_ = frame_size_in_dip;
@@ -1461,6 +1484,7 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
+ window_->SchedulePaintInRect(damage_rect_in_dip);
ui::Compositor* compositor = GetCompositor();
if (!compositor) {
@@ -1493,7 +1517,8 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
gfx::Size frame_size_in_dip =
ConvertSizeToDIP(frame_device_scale_factor, frame_size);
if (ShouldSkipFrame(frame_size_in_dip)) {
- SendSoftwareFrameAck(output_surface_id, frame_data->id);
+ ReleaseSoftwareFrame(output_surface_id, frame_data->id);
+ SendSoftwareFrameAck(output_surface_id);
return;
}
@@ -1522,41 +1547,83 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
scoped_refptr<MemoryHolder> holder(new MemoryHolder(
shared_memory.Pass(),
frame_size,
- base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ base::Bind(&RenderWidgetHostViewAura::ReleaseSoftwareFrame,
AsWeakPtr(),
output_surface_id,
frame_data->id)));
framebuffer_holder_.swap(holder);
- cc::TextureMailbox mailbox = framebuffer_holder_->GetMailbox();
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ framebuffer_holder_->GetMailbox(&mailbox, &callback);
DCHECK(mailbox.IsSharedMemory());
current_frame_size_ = frame_size_in_dip;
released_front_lock_ = NULL;
CheckResizeLock();
- window_->layer()->SetTextureMailbox(mailbox, frame_device_scale_factor);
+ window_->layer()->SetTextureMailbox(mailbox,
+ callback.Pass(),
+ frame_device_scale_factor);
window_->SchedulePaintInRect(
ConvertRectToDIP(frame_device_scale_factor, damage_rect));
ui::Compositor* compositor = GetCompositor();
- if (compositor)
+ if (compositor) {
compositor->SetLatencyInfo(latency_info);
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ AsWeakPtr(),
+ output_surface_id));
+ }
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
DidReceiveFrameFromRenderer();
+ FrameMemoryManager::GetInstance()->AddFrame(this, !host_->is_hidden());
}
-void RenderWidgetHostViewAura::SendSoftwareFrameAck(
- uint32 output_surface_id, unsigned software_frame_id) {
+void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
+ unsigned software_frame_id = 0;
+ if (!released_software_frames_.empty()) {
+ unsigned released_output_surface_id =
+ released_software_frames_.back().output_surface_id;
+ if (released_output_surface_id == output_surface_id) {
+ software_frame_id = released_software_frames_.back().frame_id;
+ released_software_frames_.pop_back();
+ }
+ }
+
cc::CompositorFrameAck ack;
ack.last_software_frame_id = software_frame_id;
RenderWidgetHostImpl::SendSwapCompositorFrameAck(
host_->GetRoutingID(), output_surface_id,
host_->GetProcess()->GetID(), ack);
+ SendReclaimSoftwareFrames();
+}
+
+void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() {
+ while (!released_software_frames_.empty()) {
+ cc::CompositorFrameAck ack;
+ ack.last_software_frame_id = released_software_frames_.back().frame_id;
+ RenderWidgetHostImpl::SendReclaimCompositorResources(
+ host_->GetRoutingID(),
+ released_software_frames_.back().output_surface_id,
+ host_->GetProcess()->GetID(),
+ ack);
+ released_software_frames_.pop_back();
+ }
+}
+
+void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
+ uint32 output_surface_id,
+ unsigned software_frame_id) {
+ SendReclaimSoftwareFrames();
+ released_software_frames_.push_back(
+ ReleasedFrameInfo(output_surface_id, software_frame_id));
}
void RenderWidgetHostViewAura::OnSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
if (frame->delegated_frame_data) {
SwapDelegatedFrame(output_surface_id,
frame->delegated_frame_data.Pass(),
@@ -1620,6 +1687,8 @@ void RenderWidgetHostViewAura::BuffersSwapped(
const BufferPresentedCallback& ack_callback) {
scoped_refptr<ui::Texture> previous_texture(current_surface_);
const gfx::Rect surface_rect = gfx::Rect(surface_size);
+ framebuffer_holder_ = NULL;
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
if (!SwapBuffersPrepare(surface_rect,
surface_scale_factor,
@@ -1724,7 +1793,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
}
bool RenderWidgetHostViewAura::HasAcceleratedSurface(
- const gfx::Size& desired_size) {
+ const gfx::Size& desired_size) {
// Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
// matter what is returned here as GetBackingStore is the only caller of this
// method. TODO(jbates) implement this if other Aura code needs it.
@@ -1756,12 +1825,12 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult(
static void CopyFromCompositingSurfaceFinished(
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
scoped_ptr<SkBitmap> bitmap,
scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
bitmap_pixels_lock.reset();
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result, *bitmap);
}
@@ -1793,23 +1862,25 @@ void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
new SkAutoLockPixels(*bitmap));
uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ cc::TextureMailbox texture_mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+ if (!texture_mailbox.IsTexture())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
result->size(),
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
- texture_mailbox->callback(),
+ base::Passed(&release_callback),
base::Passed(&bitmap),
base::Passed(&bitmap_pixels_lock)));
}
@@ -1831,7 +1902,7 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
if (!source)
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
SkBitmap bitmap = skia::ImageOperations::Resize(
*source,
@@ -1843,9 +1914,9 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
static void CopyFromCompositingSurfaceFinishedForVideo(
const base::Callback<void(bool)>& callback,
- const cc::TextureMailbox::ReleaseCallback& release_callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
bool result) {
- release_callback.Run(0, false);
+ release_callback->Run(0, false);
callback.Run(result);
}
@@ -1908,7 +1979,7 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
region_in_frame,
video_frame.get());
}
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
callback.Run(true);
return;
}
@@ -1918,9 +1989,11 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
if (!gl_helper)
return;
- scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture();
- DCHECK(texture_mailbox->IsTexture());
- if (!texture_mailbox->IsTexture())
+ cc::TextureMailbox texture_mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+ if (!texture_mailbox.IsTexture())
return;
gfx::Rect result_rect(result->size());
@@ -1958,14 +2031,14 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
}
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
base::Callback<void(bool result)> finished_callback = base::Bind(
&CopyFromCompositingSurfaceFinishedForVideo,
callback,
- texture_mailbox->callback());
+ base::Passed(&release_callback));
yuv_readback_pipeline->ReadbackYUV(
- texture_mailbox->name(),
- texture_mailbox->sync_point(),
+ texture_mailbox.name(),
+ texture_mailbox.sync_point(),
video_frame.get(),
finished_callback);
}
@@ -1975,7 +2048,32 @@ void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
}
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
+#if defined(OS_WIN)
+ // aura::Window::GetBoundsInScreen doesn't take non-client area into
+ // account.
+ RECT window_rect = {0};
+
+ aura::Window* top_level = window_->GetToplevelWindow();
+ aura::RootWindow* root_window = top_level->GetRootWindow();
+ if (!root_window)
+ return top_level->GetBoundsInScreen();
+ HWND hwnd = root_window->GetAcceleratedWidget();
+ ::GetWindowRect(hwnd, &window_rect);
+ gfx::Rect rect(window_rect);
+
+ // Maximized windows are outdented from the work area by the frame thickness
+ // even though this "frame" is not painted. This confuses code (and people)
+ // that think of a maximized window as corresponding exactly to the work area.
+ // Correct for this by subtracting the frame thickness back off.
+ if (::IsZoomed(hwnd)) {
+ rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
+ GetSystemMetrics(SM_CYSIZEFRAME));
+ }
+
+ return gfx::win::ScreenToDIPRect(rect);
+#else
return window_->GetToplevelWindow()->GetBoundsInScreen();
+#endif
}
void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type,
@@ -2004,7 +2102,7 @@ void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
}
}
-SmoothScrollGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
+SyntheticGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
bool scroll_down,
int pixels_to_scroll,
int mouse_event_x,
@@ -2026,12 +2124,12 @@ void RenderWidgetHostViewAura::SetScrollOffsetPinning(
// Not needed. Mac-only.
}
-void RenderWidgetHostViewAura::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewAura::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
- manager->OnAccessibilityNotifications(params);
+ manager->OnAccessibilityEvents(params);
}
gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
@@ -2122,7 +2220,7 @@ void RenderWidgetHostViewAura::SetCompositionText(
void RenderWidgetHostViewAura::ConfirmCompositionText() {
if (host_ && has_composition_text_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
has_composition_text_ = false;
}
@@ -2135,7 +2233,7 @@ void RenderWidgetHostViewAura::ClearCompositionText() {
void RenderWidgetHostViewAura::InsertText(const string16& text) {
DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
if (host_)
- host_->ImeConfirmComposition(text, ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
has_composition_text_ = false;
}
@@ -2166,7 +2264,7 @@ ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
}
ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
- return ui::TEXT_INPUT_MODE_DEFAULT;
+ return text_input_mode_;
}
bool RenderWidgetHostViewAura::CanComposeInline() const {
@@ -2178,18 +2276,18 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
gfx::Point end = gfx::Point(rect.right(), rect.bottom());
aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root_window);
- screen_position_client->ConvertPointToScreen(window_, &origin);
- screen_position_client->ConvertPointToScreen(window_, &end);
- return gfx::Rect(origin.x(),
- origin.y(),
- end.x() - origin.x(),
- end.y() - origin.y());
- }
-
- return rect;
+ if (!root_window)
+ return rect;
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root_window);
+ if (!screen_position_client)
+ return rect;
+ screen_position_client->ConvertPointToScreen(window_, &origin);
+ screen_position_client->ConvertPointToScreen(window_, &end);
+ return gfx::Rect(origin.x(),
+ origin.y(),
+ end.x() - origin.x(),
+ end.y() - origin.y());
}
gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
@@ -2231,40 +2329,40 @@ bool RenderWidgetHostViewAura::HasCompositionText() {
return has_composition_text_;
}
-bool RenderWidgetHostViewAura::GetTextRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) {
range->set_start(selection_text_offset_);
range->set_end(selection_text_offset_ + selection_text_.length());
return true;
}
-bool RenderWidgetHostViewAura::GetCompositionTextRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetCompositionTextRange(gfx::Range* range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
-bool RenderWidgetHostViewAura::GetSelectionRange(ui::Range* range) {
+bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) {
range->set_start(selection_range_.start());
range->set_end(selection_range_.end());
return true;
}
-bool RenderWidgetHostViewAura::SetSelectionRange(const ui::Range& range) {
+bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
-bool RenderWidgetHostViewAura::DeleteRange(const ui::Range& range) {
+bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
bool RenderWidgetHostViewAura::GetTextFromRange(
- const ui::Range& range,
+ const gfx::Range& range,
string16* text) {
- ui::Range selection_text_range(selection_text_offset_,
+ gfx::Range selection_text_range(selection_text_offset_,
selection_text_offset_ + selection_text_.length());
if (!selection_text_range.Contains(range)) {
@@ -2446,6 +2544,13 @@ void RenderWidgetHostViewAura::OnWindowDestroying() {
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, WindowDestroyingCallback, lparam);
#endif
+
+ // Make sure that the input method no longer references to this object before
+ // this object is removed from the root window (i.e. this object loses access
+ // to the input method).
+ ui::InputMethod* input_method = GetInputMethod();
+ if (input_method)
+ input_method->DetachTextInputClient(this);
}
void RenderWidgetHostViewAura::OnWindowDestroyed() {
@@ -2463,28 +2568,53 @@ bool RenderWidgetHostViewAura::HasHitTestMask() const {
void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
}
-scoped_refptr<ui::Texture> RenderWidgetHostViewAura::CopyTexture() {
- if (!host_->is_accelerated_compositing_active())
- return scoped_refptr<ui::Texture>();
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return scoped_refptr<ui::Texture>();
-
- if (!current_surface_.get())
- return scoped_refptr<ui::Texture>();
-
- WebKit::WebGLId texture_id =
- gl_helper->CopyTexture(current_surface_->PrepareTexture(),
- current_surface_->size());
- if (!texture_id)
- return scoped_refptr<ui::Texture>();
-
- return scoped_refptr<ui::Texture>(
- factory->CreateOwnedTexture(
+void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) {
+ float mailbox_scale_factor;
+ cc::TextureMailbox old_mailbox =
+ old_layer->GetTextureMailbox(&mailbox_scale_factor);
+ scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
+ // The new_layer is the one that will be used by our Window, so that's the one
+ // that should keep our texture. old_layer will be returned to the
+ // RecreateLayer caller, and should have a copy.
+ if (old_texture.get()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ scoped_refptr<ui::Texture> new_texture;
+ if (host_->is_accelerated_compositing_active() &&
+ gl_helper && current_surface_.get()) {
+ WebKit::WebGLId texture_id =
+ gl_helper->CopyTexture(current_surface_->PrepareTexture(),
+ current_surface_->size());
+ if (texture_id) {
+ new_texture = factory->CreateOwnedTexture(
current_surface_->size(),
- current_surface_->device_scale_factor(), texture_id));
+ current_surface_->device_scale_factor(), texture_id);
+ }
+ }
+ old_layer->SetExternalTexture(new_texture);
+ new_layer->SetExternalTexture(old_texture);
+ } else if (old_mailbox.IsSharedMemory()) {
+ base::SharedMemory* old_buffer = old_mailbox.shared_memory();
+ const size_t size = old_mailbox.shared_memory_size_in_bytes();
+
+ scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
+ new_buffer->CreateAndMapAnonymous(size);
+
+ if (old_buffer->memory() && new_buffer->memory()) {
+ memcpy(new_buffer->memory(), old_buffer->memory(), size);
+ base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
+ scoped_ptr<cc::SingleReleaseCallback> callback =
+ cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
+ Passed(&new_buffer)));
+ cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
+ old_mailbox.shared_memory_size());
+ new_layer->SetTextureMailbox(new_mailbox,
+ callback.Pass(),
+ mailbox_scale_factor);
+ }
+ }
+ // TODO(piman): handle delegated frames.
}
////////////////////////////////////////////////////////////////////////////////
@@ -2859,6 +2989,18 @@ void RenderWidgetHostViewAura::OnRootWindowHostMoved(
UpdateScreenInfo(window_);
}
+void RenderWidgetHostViewAura::ReleaseCurrentFrame() {
+ if (framebuffer_holder_.get() && !current_surface_.get()) {
+ framebuffer_holder_ = NULL;
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ AddOnCommitCallbackAndDisableLocks(base::Bind(
+ &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
+ }
+ UpdateExternalTexture();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, ui::CompositorObserver implementation:
@@ -2908,8 +3050,17 @@ void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) {
- if (IsShowing() && !last_draw_ended_.is_null())
- host_->UpdateVSyncParameters(last_draw_ended_, interval);
+ if (IsShowing()) {
+ if (IsDeadlineSchedulingEnabled()) {
+ // The deadline scheduler has logic to stagger the draws of the
+ // Renderer and Browser built-in, so send it an accurate timebase.
+ host_->UpdateVSyncParameters(timebase, interval);
+ } else if (!last_draw_ended_.is_null()) {
+ // For the non-deadline scheduler, we send the Renderer an offset
+ // vsync timebase to avoid its draws racing the Browser's draws.
+ host_->UpdateVSyncParameters(last_draw_ended_, interval);
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -3021,6 +3172,7 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
// Aura root window and we don't have a way to get an input method object
// associated with the window, but just in case.
DetachFromInputMethod();
+ FrameMemoryManager::GetInstance()->RemoveFrame(this);
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
@@ -3034,8 +3186,10 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
gfx::Point local_point = screen_point;
local_point.Offset(-screen_rect.x(), -screen_rect.y());
- if (root_window->GetEventHandlerForPoint(local_point) != window_)
+ if (!root_window->HasFocus() ||
+ root_window->GetEventHandlerForPoint(local_point) != window_) {
return;
+ }
gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
// Do not show loading cursor when the cursor is currently hidden.
@@ -3064,7 +3218,7 @@ void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
if (host_)
- host_->ImeConfirmComposition(string16(), ui::Range::InvalidRange(), false);
+ host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
ImeCancelComposition();
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
index c4a16271634..f5939df0fc7 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -18,6 +18,7 @@
#include "cc/resources/texture_mailbox.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/aura/image_transport_factory.h"
+#include "content/browser/renderer_host/frame_memory_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/gl_helper.h"
@@ -59,9 +60,10 @@ namespace content {
class MemoryHolder;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
+class ResizeLock;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
-class RenderWidgetHostViewAura
+class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
public ui::CompositorObserver,
public ui::TextInputClient,
@@ -74,6 +76,7 @@ class RenderWidgetHostViewAura
public aura::client::CursorClientObserver,
public ImageTransportFactoryObserver,
public BrowserAccessibilityDelegate,
+ public FrameContainer,
public base::SupportsWeakPtr<RenderWidgetHostViewAura> {
public:
// Used to notify whenever the paint-content of the view changes.
@@ -155,10 +158,6 @@ class RenderWidgetHostViewAura
virtual bool IsShowing() OVERRIDE;
virtual gfx::Rect GetViewBounds() const OVERRIDE;
virtual void SetBackground(const SkBitmap& background) OVERRIDE;
-#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
// Overridden from RenderWidgetHostViewPort:
virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -175,11 +174,11 @@ class RenderWidgetHostViewAura
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -192,7 +191,7 @@ class RenderWidgetHostViewAura
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -227,7 +226,7 @@ class RenderWidgetHostViewAura
virtual void ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down,
int pixels_to_scroll,
int mouse_event_x,
@@ -237,8 +236,8 @@ class RenderWidgetHostViewAura
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -265,12 +264,12 @@ class RenderWidgetHostViewAura
virtual bool GetCompositionCharacterBounds(uint32 index,
gfx::Rect* rect) OVERRIDE;
virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(ui::Range* range) OVERRIDE;
- virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE;
- virtual bool DeleteRange(const ui::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const ui::Range& range,
+ virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE;
+ virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
+ virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
+ virtual bool GetTextFromRange(const gfx::Range& range,
string16* text) OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
@@ -302,7 +301,8 @@ class RenderWidgetHostViewAura
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE;
+ virtual void DidRecreateLayer(ui::Layer *old_layer,
+ ui::Layer *new_layer) OVERRIDE;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
@@ -329,6 +329,9 @@ class RenderWidgetHostViewAura
virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
const gfx::Point& new_origin) OVERRIDE;
+ // FrameContainer implementation:
+ virtual void ReleaseCurrentFrame() OVERRIDE;
+
bool CanCopyToBitmap() const;
#if defined(OS_WIN)
@@ -340,25 +343,21 @@ class RenderWidgetHostViewAura
protected:
friend class RenderWidgetHostView;
+ virtual ~RenderWidgetHostViewAura();
- // Should construct only via RenderWidgetHostView::CreateViewForWidget.
+ // Should be constructed via RenderWidgetHostView::CreateViewForWidget.
explicit RenderWidgetHostViewAura(RenderWidgetHost* host);
RenderWidgetHostViewFrameSubscriber* frame_subscriber() const {
return frame_subscriber_.get();
}
- private:
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
+ virtual bool ShouldCreateResizeLock();
+ virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock);
- class WindowObserver;
- friend class WindowObserver;
-#if defined(OS_WIN)
- class TransientWindowObserver;
- friend class TransientWindowObserver;
-#endif
+ // Exposed for tests.
+ aura::Window* window() { return window_; }
+ gfx::Size current_frame_size() const { return current_frame_size_; }
// Overridden from ui::CompositorObserver:
virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE;
@@ -372,6 +371,21 @@ class RenderWidgetHostViewAura
base::TimeTicks timebase,
base::TimeDelta interval) OVERRIDE;
+ private:
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ SkippedDelegatedFrames);
+
+ class WindowObserver;
+ friend class WindowObserver;
+#if defined(OS_WIN)
+ class TransientWindowObserver;
+ friend class TransientWindowObserver;
+#endif
+
// Overridden from ImageTransportFactoryObserver:
virtual void OnLostResources() OVERRIDE;
@@ -387,8 +401,6 @@ class RenderWidgetHostViewAura
virtual gfx::Point GetLastTouchEventLocation() const OVERRIDE;
virtual void FatalAccessibilityTreeError() OVERRIDE;
- virtual ~RenderWidgetHostViewAura();
-
void UpdateCursorIfOverSelf();
bool ShouldSkipFrame(gfx::Size size_in_dip) const;
@@ -509,7 +521,9 @@ class RenderWidgetHostViewAura
scoped_ptr<cc::SoftwareFrameData> frame_data,
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info);
- void SendSoftwareFrameAck(uint32 output_surface_id,
+ void SendSoftwareFrameAck(uint32 output_surface_id);
+ void SendReclaimSoftwareFrames();
+ void ReleaseSoftwareFrame(uint32 output_surface_id,
unsigned software_frame_id);
void DidReceiveFrameFromRenderer();
@@ -565,6 +579,8 @@ class RenderWidgetHostViewAura
// The current text input type.
ui::TextInputType text_input_type_;
+ // The current text input mode corresponding to HTML5 inputmode attribute.
+ ui::TextInputMode text_input_mode_;
bool can_compose_inline_;
// Rectangles for the selection anchor and focus.
@@ -588,12 +604,21 @@ class RenderWidgetHostViewAura
// This holds the current software framebuffer.
scoped_refptr<MemoryHolder> framebuffer_holder_;
+ // With delegated renderer, this is the last output surface, used to
+ // disambiguate resources with the same id coming from different output
+ // surfaces.
+ uint32 last_output_surface_id_;
+
// The damage in the previously presented buffer.
SkRegion previous_damage_;
// Pending damage from previous frames that we skipped.
SkRegion skipped_damage_;
+ // True after a delegated frame has been skipped, until a frame is not
+ // skipped.
+ bool skipped_frames_;
+
// The size of the last frame that was swapped (even if we skipped it).
// Used to determine when the skipped_damage_ needs to be reset due to
// size changes between front- and backbuffer.
@@ -625,9 +650,6 @@ class RenderWidgetHostViewAura
// software backing store is updated.
bool accelerated_compositing_state_changed_;
- // Used to prevent further resizes while a resize is pending.
- class ResizeLock;
-
// This lock is the one waiting for a frame of the right size to come back
// from the renderer/GPU process. It is set from the moment the aura window
// got resized, to the moment we committed the renderer frame of the same
@@ -700,6 +722,14 @@ class RenderWidgetHostViewAura
ui::LatencyInfo software_latency_info_;
+ struct ReleasedFrameInfo {
+ ReleasedFrameInfo(uint32 output_id, unsigned software_frame_id)
+ : output_surface_id(output_id), frame_id(software_frame_id) {}
+ uint32 output_surface_id;
+ unsigned frame_id;
+ };
+ std::vector<ReleasedFrameInfo> released_software_frames_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 03f7d5c591f..824db746ceb 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -5,16 +5,24 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_metadata.h"
+#include "cc/output/gl_frame_data.h"
+#include "content/browser/aura/resize_lock.h"
+#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "ipc/ipc_test_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
@@ -26,9 +34,11 @@
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/ui_base_types.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+
+using testing::_;
namespace content {
namespace {
@@ -69,11 +79,48 @@ class TestWindowObserver : public aura::WindowObserver {
DISALLOW_COPY_AND_ASSIGN(TestWindowObserver);
};
+class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
+ public:
+ FakeRenderWidgetHostViewAura(RenderWidgetHost* widget)
+ : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {}
+
+ virtual ~FakeRenderWidgetHostViewAura() {}
+
+ virtual bool ShouldCreateResizeLock() OVERRIDE {
+ gfx::Size desired_size = window()->bounds().size();
+ return desired_size != current_frame_size();
+ }
+
+ virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock)
+ OVERRIDE {
+ gfx::Size desired_size = window()->bounds().size();
+ return scoped_ptr<ResizeLock>(
+ new FakeResizeLock(desired_size, defer_compositor_lock));
+ }
+
+ void RunOnCompositingDidCommit() {
+ OnCompositingDidCommit(window()->GetRootWindow()->compositor());
+ }
+
+ // A lock that doesn't actually do anything to the compositor, and does not
+ // time out.
+ class FakeResizeLock : public ResizeLock {
+ public:
+ FakeResizeLock(const gfx::Size new_size, bool defer_compositor_lock)
+ : ResizeLock(new_size, defer_compositor_lock) {}
+ };
+
+ bool has_resize_lock_;
+ gfx::Size last_frame_size_;
+};
+
class RenderWidgetHostViewAuraTest : public testing::Test {
public:
- RenderWidgetHostViewAuraTest() {}
+ RenderWidgetHostViewAuraTest()
+ : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
virtual void SetUp() {
+ ImageTransportFactory::InitializeForUnitTests();
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
@@ -84,7 +131,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
sink_ = &process_host->sink();
parent_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
parent_view_ = static_cast<RenderWidgetHostViewAura*>(
RenderWidgetHostView::CreateViewForWidget(parent_host_));
parent_view_->InitAsChild(NULL);
@@ -92,10 +139,11 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
aura_test_helper_->root_window(), gfx::Rect());
widget_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
widget_host_->Init();
- view_ = static_cast<RenderWidgetHostViewAura*>(
- RenderWidgetHostView::CreateViewForWidget(widget_host_));
+ widget_host_->OnMessageReceived(
+ ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
+ view_ = new FakeRenderWidgetHostViewAura(widget_host_);
}
virtual void TearDown() {
@@ -112,10 +160,12 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
message_loop_.DeleteSoon(FROM_HERE, browser_context_.release());
message_loop_.RunUntilIdle();
+ ImageTransportFactory::Terminate();
}
protected:
base::MessageLoopForUI message_loop_;
+ BrowserThreadImpl browser_thread_for_ui_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<BrowserContext> browser_context_;
MockRenderWidgetHostDelegate delegate_;
@@ -128,7 +178,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
// Tests should set these to NULL if they've already triggered their
// destruction.
RenderWidgetHostImpl* widget_host_;
- RenderWidgetHostViewAura* view_;
+ FakeRenderWidgetHostViewAura* view_;
IPC::TestSink* sink_;
@@ -170,6 +220,11 @@ class FullscreenLayoutManager : public aura::LayoutManager {
DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager);
};
+class MockWindowObserver : public aura::WindowObserver {
+ public:
+ MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&));
+};
+
} // namespace
// Checks that a fullscreen view has the correct show-state and receives the
@@ -231,7 +286,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
const ui::CompositionUnderlines& underlines = composition_text.underlines;
// Caret is at the end. (This emulates Japanese MSIME 2007 and later)
- composition_text.selection = ui::Range(4);
+ composition_text.selection = gfx::Range(4);
sink_->ClearMessages();
view_->SetCompositionText(composition_text);
@@ -584,4 +639,209 @@ TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
}
}
+scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->gl_frame_data.reset(new cc::GLFrameData);
+ frame->gl_frame_data->sync_point = 1;
+ memset(frame->gl_frame_data->mailbox.name, '1', 64);
+ frame->gl_frame_data->size = size;
+ frame->gl_frame_data->sub_buffer_rect = damage;
+ return frame.Pass();
+}
+
+scoped_ptr<cc::CompositorFrame> MakeSoftwareFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->software_frame_data.reset(new cc::SoftwareFrameData);
+ frame->software_frame_data->id = 1;
+ frame->software_frame_data->size = size;
+ frame->software_frame_data->damage_rect = damage;
+ base::SharedMemory shm;
+ shm.CreateAndMapAnonymous(size.GetArea() * 4);
+ shm.GiveToProcess(base::GetCurrentProcessHandle(),
+ &frame->software_frame_data->handle);
+ return frame.Pass();
+}
+
+scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
+
+ scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
+ pass->SetNew(cc::RenderPass::Id(1, 1),
+ gfx::Rect(size),
+ gfx::RectF(damage),
+ gfx::Transform());
+ frame->delegated_frame_data->render_pass_list.push_back(pass.Pass());
+ return frame.Pass();
+}
+
+// Swapping a frame should notify the window.
+TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
+ gfx::Size view_size(100, 100);
+ gfx::Rect view_rect(view_size);
+
+ view_->InitAsChild(NULL);
+ view_->GetNativeView()->SetDefaultParentByRootWindow(
+ parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ view_->SetSize(view_size);
+ view_->WasShown();
+
+ MockWindowObserver observer;
+ view_->window_->AddObserver(&observer);
+
+ // Swap a frame through the GPU path.
+ GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
+ params.surface_id = widget_host_->surface_id();
+ params.route_id = widget_host_->GetRoutingID();
+ params.mailbox_name = std::string(64, '1');
+ params.size = view_size;
+ params.scale_factor = 1.f;
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // DSF = 2
+ params.size = gfx::Size(200, 200);
+ params.scale_factor = 2.f;
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Partial frames though GPU path
+ GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params post_params;
+ post_params.surface_id = widget_host_->surface_id();
+ post_params.route_id = widget_host_->GetRoutingID();
+ post_params.mailbox_name = std::string(64, '1');
+ post_params.surface_size = gfx::Size(200, 200);
+ post_params.surface_scale_factor = 2.f;
+ post_params.x = 40;
+ post_params.y = 40;
+ post_params.width = 80;
+ post_params.height = 80;
+ // rect from params is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(19, 39, 42, 42)));
+ view_->AcceleratedSurfacePostSubBuffer(post_params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Composite-to-mailbox path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(0, MakeGLFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // rect from GL frame is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(4, 89, 7, 7)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeGLFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Software path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(0, MakeSoftwareFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(5, 5, 5, 5)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeSoftwareFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Delegated renderer path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(5, 5, 5, 5)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ view_->window_->RemoveObserver(&observer);
+}
+
+// Skipped frames should not drop their damage.
+TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
+ gfx::Rect view_rect(100, 100);
+ gfx::Size frame_size = view_rect.size();
+
+ view_->InitAsChild(NULL);
+ view_->GetNativeView()->SetDefaultParentByRootWindow(
+ parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ view_->SetSize(view_rect.size());
+
+ MockWindowObserver observer;
+ view_->window_->AddObserver(&observer);
+
+ // A full frame of damage.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // A partial damage frame.
+ gfx::Rect partial_view_rect(30, 30, 20, 20);
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Lock the compositor. Now we should drop frames.
+ view_rect = gfx::Rect(150, 150);
+ view_->SetSize(view_rect.size());
+ view_->MaybeCreateResizeLock();
+
+ // This frame is dropped.
+ gfx::Rect dropped_damage_rect_1(10, 20, 30, 40);
+ EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ gfx::Rect dropped_damage_rect_2(40, 50, 10, 20);
+ EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Unlock the compositor. This frame should damage everything.
+ frame_size = view_rect.size();
+
+ gfx::Rect new_damage_rect(5, 6, 10, 10);
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // A partial damage frame, this should not be dropped.
+ EXPECT_CALL(observer,
+ OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+
+ view_->window_->RemoveObserver(&observer);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
index d6b1e789e2a..57181031f22 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -11,7 +11,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/port/browser/synthetic_gesture.h"
#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
@@ -29,9 +29,9 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/common/content_switches.h"
-#include "ui/base/win/dpi.h"
-#include "ui/base/win/hwnd_util.h"
#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/hwnd_util.h"
#endif
#if defined(TOOLKIT_GTK)
@@ -118,7 +118,7 @@ LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
}
bool IsPluginWrapperWindow(HWND window) {
- return ui::GetClassNameW(window) ==
+ return gfx::GetClassNameW(window) ==
string16(kWrapperNativeWindowClassName);
}
@@ -151,7 +151,7 @@ HWND ReparentWindow(HWND window, HWND parent) {
MAKEINTATOM(atom), 0,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 0, 0, parent, 0, instance, 0);
- ui::CheckWindowCreated(new_parent);
+ gfx::CheckWindowCreated(new_parent);
::SetParent(window, new_parent);
// How many times we try to find a PluginProcessHost whose process matches
// the HWND.
@@ -169,7 +169,7 @@ BOOL CALLBACK PaintEnumChildProc(HWND hwnd, LPARAM lparam) {
return TRUE;
gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
- gfx::Rect rect_in_pixels = ui::win::DIPToScreenRect(*rect);
+ gfx::Rect rect_in_pixels = gfx::win::DIPToScreenRect(*rect);
static UINT msg = RegisterWindowMessage(kPaintMessageName);
WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());
@@ -284,7 +284,7 @@ void RenderWidgetHostViewBase::MovePluginWindowsHelper(
#endif
if (move.rects_valid) {
- gfx::Rect clip_rect_in_pixel = ui::win::DIPToScreenRect(move.clip_rect);
+ gfx::Rect clip_rect_in_pixel = gfx::win::DIPToScreenRect(move.clip_rect);
HRGN hrgn = ::CreateRectRgn(clip_rect_in_pixel.x(),
clip_rect_in_pixel.y(),
clip_rect_in_pixel.right(),
@@ -313,7 +313,7 @@ void RenderWidgetHostViewBase::MovePluginWindowsHelper(
}
gfx::Rect window_rect_in_pixel =
- ui::win::DIPToScreenRect(move.window_rect);
+ gfx::win::DIPToScreenRect(move.window_rect);
defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
window, NULL,
window_rect_in_pixel.x(),
@@ -382,7 +382,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
mouse_locked_(false),
showing_context_menu_(false),
selection_text_offset_(0),
- selection_range_(ui::Range::InvalidRange()),
+ selection_range_(gfx::Range::InvalidRange()),
current_device_scale_factor_(0),
renderer_frame_number_(0) {
}
@@ -417,7 +417,7 @@ float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
void RenderWidgetHostViewBase::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
selection_text_ = text;
selection_text_offset_ = offset;
selection_range_.set_start(range.start());
@@ -501,13 +501,21 @@ bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
return true;
}
-SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
+SyntheticGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) {
return new BasicMouseWheelSmoothScrollGesture(scroll_down, pixels_to_scroll,
mouse_event_x, mouse_event_y);
}
+SyntheticGesture* RenderWidgetHostViewBase::CreatePinchGesture(
+ bool zoom_in, int pixels_to_move, int anchor_x,
+ int anchor_y) {
+ // There is no generic implementation for pinch gestures.
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
index 68fcaffaea7..0472153b275 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
@@ -20,8 +20,8 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "ui/base/range/range.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
namespace content {
@@ -48,7 +48,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SetBackground(const SkBitmap& background) OVERRIDE;
virtual const SkBitmap& GetBackground() OVERRIDE;
virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE;
@@ -69,9 +69,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
GetBrowserAccessibilityManager() const OVERRIDE;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) OVERRIDE;
+ virtual SyntheticGesture* CreatePinchGesture(
+ bool zoom_in, int pixels_to_move, int anchor_x,
+ int anchor_y) OVERRIDE;
virtual bool CanSubscribeFrame() const OVERRIDE;
virtual void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
@@ -144,7 +147,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
size_t selection_text_offset_;
// The current selection range relative to the start of the web page.
- ui::Range selection_range_;
+ gfx::Range selection_range_;
protected:
// The scale factor of the display the renderer is currently on.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 2b47ff19315..0fe376e65b3 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -6,29 +6,30 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/public/browser/compositor_util.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "media/base/video_frame.h"
#include "media/filters/skcanvas_video_renderer.h"
#include "net/base/net_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#if defined(OS_MACOSX)
@@ -36,7 +37,8 @@
#endif
#if defined(OS_WIN)
-#include "ui/base/win/dpi.h"
+#include "base/win/windows_version.h"
+#include "ui/gfx/win/dpi.h"
#endif
namespace content {
@@ -341,6 +343,14 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
// is enabled.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
CopyFromBackingStore) {
+ // Disable the test for WinXP. See http://crbug/294116.
+#if defined(OS_WIN)
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
+ return;
+ }
+#endif
+
RunBasicCopyFromBackingStoreTest();
}
@@ -373,8 +383,18 @@ IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
// Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
// always called, even when the RenderWidgetHost is deleting in the middle of
// an async copy.
+//
+// Test is flaky on Win Aura. http://crbug.com/276783
+#if (defined(OS_WIN) && defined(USE_AURA)) || \
+ (defined(OS_CHROMEOS) && !defined(NDEBUG))
+#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
+ DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
+#else
+#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
+ CopyFromCompositingSurface_CallbackDespiteDelete
+#endif
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
- CopyFromCompositingSurface_CallbackDespiteDelete) {
+ MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanCopyToVideoFrame()) {
@@ -410,6 +430,14 @@ IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
// until at least one DeliverFrameCallback has been invoked.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
FrameSubscriberTest) {
+ // Disable the test for WinXP. See http://crbug/294116.
+#if defined(OS_WIN)
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
+ return;
+ }
+#endif
+
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanSubscribeFrame()) {
@@ -435,6 +463,14 @@ IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
// Test that we can copy twice from an accelerated composited page.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
+ // Disable the test for WinXP. See http://crbug/294116.
+#if defined(OS_WIN)
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
+ return;
+ }
+#endif
+
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanCopyToVideoFrame()) {
@@ -558,7 +594,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
bitmap.allocPixels();
bitmap.setIsOpaque(true);
- SkDevice device(bitmap);
+ SkBitmapDevice device(bitmap);
SkCanvas canvas(&device);
video_renderer.Paint(video_frame.get(),
@@ -638,7 +674,8 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
// The page is loaded in the renderer, wait for a new frame to arrive.
uint32 frame = rwhvp->RendererFrameNumber();
- GetRenderWidgetHost()->ScheduleComposite();
+ while (!GetRenderWidgetHost()->ScheduleComposite())
+ GiveItSomeTime();
while (rwhvp->RendererFrameNumber() == frame)
GiveItSomeTime();
@@ -824,7 +861,7 @@ class CompositingRenderWidgetHostViewTabCaptureHighDPI
base::StringPrintf("%f", scale()));
#if defined(OS_WIN)
cmd->AppendSwitchASCII(switches::kHighDPISupport, "1");
- ui::EnableHighDPISupport();
+ gfx::EnableHighDPISupport();
#endif
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
index ddaf9528cfd..61512ef7506 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -29,6 +29,7 @@
#include "content/browser/renderer_host/gtk_im_context_wrapper.h"
#include "content/browser/renderer_host/gtk_key_bindings_handler.h"
#include "content/browser/renderer_host/gtk_window_utils.h"
+#include "content/browser/renderer_host/input/web_input_event_builders_gtk.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
@@ -40,17 +41,15 @@
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebScreenInfo.h"
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/gtk/gtk_compat.h"
-#include "ui/base/text/text_elider.h"
#include "ui/base/x/active_window_watcher_x.h"
#include "ui/base/x/x11_util.h"
+#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_native_view_id_manager.h"
#include "ui/gfx/gtk_preserve_window.h"
+#include "ui/gfx/text_elider.h"
#include "webkit/common/cursors/webcursor_gtk_data.h"
-using WebKit::WebInputEventFactory;
using WebKit::WebMouseWheelEvent;
using WebKit::WebScreenInfo;
@@ -70,10 +69,6 @@ namespace {
const int kMaxWindowWidth = 10000;
const int kMaxWindowHeight = 10000;
-// See WebInputEventFactor.cpp for a reason for this being the default
-// scroll size for linux.
-const float kDefaultScrollPixelsPerTick = 160.0f / 3.0f;
-
const GdkColor kBGColor =
#if defined(NDEBUG)
{ 0, 0xff * 257, 0xff * 257, 0xff * 257 };
@@ -354,7 +349,7 @@ class RenderWidgetHostViewGtkWidget {
RenderWidgetHostImpl* widget_host =
RenderWidgetHostImpl::From(host_view->GetRenderWidgetHost());
if (widget_host)
- widget_host->ForwardMouseEvent(WebInputEventFactory::mouseEvent(event));
+ widget_host->ForwardMouseEvent(WebMouseEventBuilder::Build(event));
// Although we did handle the mouse event, we need to let other handlers
// run (in particular the one installed by WebContentsViewGtk).
@@ -380,8 +375,7 @@ class RenderWidgetHostViewGtkWidget {
host_view->ModifyEventForEdgeDragging(widget, event);
- WebKit::WebMouseEvent mouse_event =
- WebInputEventFactory::mouseEvent(event);
+ WebKit::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
if (host_view->mouse_locked_) {
gfx::Point center = host_view->GetWidgetCenter();
@@ -431,8 +425,7 @@ class RenderWidgetHostViewGtkWidget {
// additionally send this crossing event with the state indicating the
// button is down, it causes problems with drag and drop in WebKit.)
if (!(event->state & any_button_mask)) {
- WebKit::WebMouseEvent mouse_event =
- WebInputEventFactory::mouseEvent(event);
+ WebKit::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
host_view->ModifyEventMovementAndCoords(&mouse_event);
// When crossing out and back into a render view the movement values
// must represent the instantaneous movement of the mouse, not the jump
@@ -500,7 +493,7 @@ class RenderWidgetHostViewGtkWidget {
gdk_event_put(event);
gdk_event_free(event);
}
- return num_clicks * kDefaultScrollPixelsPerTick;
+ return num_clicks * WebMouseWheelEventBuilder::ScrollbarPixelsPerTick();
}
static gboolean OnMouseScrollEvent(GtkWidget* widget,
@@ -518,21 +511,23 @@ class RenderWidgetHostViewGtkWidget {
event->direction = GDK_SCROLL_RIGHT;
}
- WebMouseWheelEvent web_event = WebInputEventFactory::mouseWheelEvent(event);
+ WebMouseWheelEvent web_event = WebMouseWheelEventBuilder::Build(event);
+ const float pixelsPerTick =
+ WebMouseWheelEventBuilder::ScrollbarPixelsPerTick();
// We peek ahead at the top of the queue to look for additional pending
// scroll events.
if (event->direction == GDK_SCROLL_UP ||
event->direction == GDK_SCROLL_DOWN) {
if (event->direction == GDK_SCROLL_UP)
- web_event.deltaY = kDefaultScrollPixelsPerTick;
+ web_event.deltaY = pixelsPerTick;
else
- web_event.deltaY = -kDefaultScrollPixelsPerTick;
+ web_event.deltaY = -pixelsPerTick;
web_event.deltaY += GetPendingScrollDelta(true, event->state);
} else {
if (event->direction == GDK_SCROLL_LEFT)
- web_event.deltaX = kDefaultScrollPixelsPerTick;
+ web_event.deltaX = pixelsPerTick;
else
- web_event.deltaX = -kDefaultScrollPixelsPerTick;
+ web_event.deltaX = -pixelsPerTick;
web_event.deltaX += GetPendingScrollDelta(false, event->state);
}
RenderWidgetHostImpl::From(
@@ -546,7 +541,7 @@ class RenderWidgetHostViewGtkWidget {
RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
: host_(RenderWidgetHostImpl::From(widget_host)),
about_to_validate_and_paint_(false),
- is_hidden_(false),
+ is_hidden_(host_->is_hidden()),
is_loading_(false),
parent_(NULL),
is_popup_first_mouse_release_(true),
@@ -686,17 +681,18 @@ RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewGtk::WasShown() {
- if (!is_hidden_)
+ if (!host_ || !is_hidden_)
return;
if (web_contents_switch_paint_time_.is_null())
web_contents_switch_paint_time_ = base::TimeTicks::Now();
is_hidden_ = false;
+
host_->WasShown();
}
void RenderWidgetHostViewGtk::WasHidden() {
- if (is_hidden_)
+ if (!host_ || is_hidden_)
return;
// If we receive any more paint messages while we are hidden, we want to
@@ -795,10 +791,12 @@ bool RenderWidgetHostViewGtk::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewGtk::Show() {
gtk_widget_show(view_.get());
+ WasShown();
}
void RenderWidgetHostViewGtk::Hide() {
gtk_widget_hide(view_.get());
+ WasHidden();
}
bool RenderWidgetHostViewGtk::IsShowing() {
@@ -837,8 +835,8 @@ void RenderWidgetHostViewGtk::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewGtk::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
im_context_->UpdateInputMethodState(type, can_compose_inline);
}
@@ -936,7 +934,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
// this itself).
// I filed https://bugzilla.gnome.org/show_bug.cgi?id=604641 upstream.
const string16 clamped_tooltip =
- ui::TruncateString(tooltip_text, kMaxTooltipLength);
+ gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (clamped_tooltip.empty()) {
gtk_widget_set_has_tooltip(view_.get(), FALSE);
@@ -948,7 +946,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
void RenderWidgetHostViewGtk::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
if (text.empty() || range.is_empty())
@@ -1542,8 +1540,8 @@ void RenderWidgetHostViewGtk::FatalAccessibilityTreeError() {
}
}
-void RenderWidgetHostViewGtk::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewGtk::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!GetBrowserAccessibilityManager()) {
GtkWidget* parent = gtk_widget_get_parent(view_.get());
SetBrowserAccessibilityManager(
@@ -1552,7 +1550,7 @@ void RenderWidgetHostViewGtk::OnAccessibilityNotifications(
BrowserAccessibilityManagerGtk::GetEmptyDocument(),
this));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
AtkObject* RenderWidgetHostViewGtk::GetAccessible() {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
index 9ff410a07b1..fc57a1a5aad 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
@@ -17,8 +17,6 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "ipc/ipc_sender.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/animation/slide_animation.h"
#include "ui/base/gtk/gtk_signal.h"
#include "ui/base/gtk/gtk_signal_registrar.h"
#include "ui/base/gtk/owned_widget_gtk.h"
@@ -83,8 +81,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -98,7 +96,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -131,8 +129,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params)
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params)
OVERRIDE;
// ActiveWindowWatcherXObserver implementation.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
index b49ca41054e..05730b92545 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -51,7 +51,7 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHostView* platform_view)
: host_(RenderWidgetHostImpl::From(widget_host)),
guest_(guest),
- is_hidden_(false),
+ is_hidden_(host_->is_hidden()),
platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) {
#if defined(OS_WIN) || defined(USE_AURA)
gesture_recognizer_.reset(ui::GestureRecognizer::Create(this));
@@ -289,11 +289,11 @@ void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewGuest::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
RenderWidgetHostViewPort::FromRWHV(
guest_->GetEmbedderRenderWidgetHostView())->
- TextInputTypeChanged(type, can_compose_inline, input_mode);
+ TextInputTypeChanged(type, input_mode, can_compose_inline);
}
void RenderWidgetHostViewGuest::ImeCancelComposition() {
@@ -302,7 +302,7 @@ void RenderWidgetHostViewGuest::ImeCancelComposition() {
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
}
#endif
@@ -317,7 +317,7 @@ void RenderWidgetHostViewGuest::DidUpdateBackingStore(
void RenderWidgetHostViewGuest::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
platform_view_->SelectionChanged(text, offset, range);
}
@@ -375,14 +375,6 @@ void RenderWidgetHostViewGuest::SetClickthroughRegion(SkRegion* region) {
}
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
-gfx::NativeViewAccessible
-RenderWidgetHostViewGuest::AccessibleObjectFromChildId(long child_id) {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif
-
void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
bool has_horizontal_scrollbar) {
platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
@@ -412,8 +404,8 @@ void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
embedder_view->GetScreenInfo(results);
}
-void RenderWidgetHostViewGuest::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewGuest::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
}
#if defined(OS_MACOSX)
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest.h b/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
index 15b0acc1a8b..82f2eab1bac 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
@@ -10,9 +10,9 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
-#include "ui/base/events/event.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/gestures/gesture_types.h"
+#include "ui/events/event.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
@@ -65,10 +65,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#if defined(OS_WIN) && !defined(USE_AURA)
virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
// RenderWidgetHostViewPort implementation.
virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -85,12 +81,12 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
#endif
virtual void DidUpdateBackingStore(
@@ -105,7 +101,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -146,8 +142,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
#if defined(OS_MACOSX)
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
index 959f5e404a3..a112634b69d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
@@ -32,7 +32,7 @@ class RenderWidgetHostViewGuestTest : public testing::Test {
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
widget_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE);
+ &delegate_, process_host, MSG_ROUTING_NONE, false);
view_ = new RenderWidgetHostViewGuest(
widget_host_, NULL, new TestRenderWidgetHostView(widget_host_));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
index 6cbe6dc7b69..11b1d973a42 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -248,11 +248,11 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -265,7 +265,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
virtual void SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) OVERRIDE;
+ const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
@@ -284,8 +284,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
virtual void EndFrameSubscription() OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params
) OVERRIDE;
virtual bool PostProcessEventForPluginIme(
const NativeWebKeyboardEvent& event) OVERRIDE;
@@ -354,19 +354,19 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
// point to |line_breaking_point|. The |line_break_point| is valid only if
// this function returns true.
bool GetLineBreakIndex(const std::vector<gfx::Rect>& bounds,
- const ui::Range& range,
+ const gfx::Range& range,
size_t* line_break_point);
// Returns composition character boundary rectangle. The |range| is
// composition based range. Also stores |actual_range| which is corresponding
// to actually used range for returned rectangle.
- gfx::Rect GetFirstRectForCompositionRange(const ui::Range& range,
- ui::Range* actual_range);
+ gfx::Rect GetFirstRectForCompositionRange(const gfx::Range& range,
+ gfx::Range* actual_range);
// Converts from given whole character range to composition oriented range. If
- // the conversion failed, return ui::Range::InvalidRange.
- ui::Range ConvertCharacterRangeToCompositionRange(
- const ui::Range& request_range);
+ // the conversion failed, return gfx::Range::InvalidRange.
+ gfx::Range ConvertCharacterRangeToCompositionRange(
+ const gfx::Range& request_range);
// These member variables should be private, but the associated ObjC class
// needs access to them and can't be made a friend.
@@ -548,7 +548,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
base::Time next_swap_ack_time_;
// The current composition character range and its bounds.
- ui::Range composition_range_;
+ gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
// The current caret bounds.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
index 07448884b5d..b6a6c180bdf 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -7,8 +7,9 @@
#import <objc/runtime.h>
#include <QuartzCore/QuartzCore.h>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/debug/trace_event.h"
@@ -54,7 +55,7 @@
#include "ui/base/cocoa/animation_utils.h"
#import "ui/base/cocoa/fullscreen_window_manager.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/base/layout.h"
#include "ui/gfx/display.h"
#include "ui/gfx/point.h"
@@ -425,7 +426,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
allow_overlapping_views_(false),
use_core_animation_(false),
is_loading_(false),
- is_hidden_(false),
+ is_hidden_(render_widget_host_->is_hidden()),
weak_factory_(this),
fullscreen_parent_host_view_(NULL),
pending_swap_buffers_acks_weak_factory_(this),
@@ -869,6 +870,10 @@ void RenderWidgetHostViewMac::Show() {
}
void RenderWidgetHostViewMac::Hide() {
+ // We're messing with the window, so do this to ensure no flashes.
+ if (!use_core_animation_)
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
+
[cocoa_view_ setHidden:YES];
WasHidden();
@@ -905,8 +910,8 @@ void RenderWidgetHostViewMac::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewMac::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type
|| can_compose_inline_ != can_compose_inline) {
text_input_type_ = type;
@@ -930,7 +935,7 @@ void RenderWidgetHostViewMac::ImeCancelComposition() {
}
void RenderWidgetHostViewMac::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
// The RangeChanged message is only sent with valid values. The current
// caret position (start == end) will be sent if there is no IME range.
@@ -1074,7 +1079,7 @@ void RenderWidgetHostViewMac::StopSpeaking() {
//
void RenderWidgetHostViewMac::SelectionChanged(const string16& text,
size_t offset,
- const ui::Range& range) {
+ const gfx::Range& range) {
if (range.is_empty() || text.empty()) {
selected_text_.clear();
} else {
@@ -1161,7 +1166,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
gfx::Size dst_pixel_size = gfx::ToFlooredSize(
gfx::ScaleSize(dst_size, scale));
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect),
dst_pixel_size,
@@ -1192,7 +1197,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
if (src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
compositing_iosurface_->CopyToVideoFrame(
GetScaledOpenGLPixelRect(src_subrect),
target,
@@ -1485,7 +1490,7 @@ void RenderWidgetHostViewMac::GetVSyncParameters(
bool RenderWidgetHostViewMac::GetLineBreakIndex(
const std::vector<gfx::Rect>& bounds,
- const ui::Range& range,
+ const gfx::Range& range,
size_t* line_break_point) {
DCHECK(line_break_point);
if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty())
@@ -1515,8 +1520,8 @@ bool RenderWidgetHostViewMac::GetLineBreakIndex(
}
gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
- const ui::Range& range,
- ui::Range* actual_range) {
+ const gfx::Range& range,
+ gfx::Range* actual_range) {
DCHECK(actual_range);
DCHECK(!composition_bounds_.empty());
DCHECK(range.start() <= composition_bounds_.size());
@@ -1541,7 +1546,7 @@ gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
if (!GetLineBreakIndex(composition_bounds_, range, &end_idx)) {
end_idx = range.end();
}
- *actual_range = ui::Range(range.start(), end_idx);
+ *actual_range = gfx::Range(range.start(), end_idx);
gfx::Rect rect = composition_bounds_[range.start()];
for (size_t i = range.start() + 1; i < end_idx; ++i) {
rect.Union(composition_bounds_[i]);
@@ -1549,21 +1554,21 @@ gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
return rect;
}
-ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
- const ui::Range& request_range) {
+gfx::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
+ const gfx::Range& request_range) {
if (composition_range_.is_empty())
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
if (request_range.is_reversed())
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
if (request_range.start() < composition_range_.start() ||
request_range.start() > composition_range_.end() ||
request_range.end() > composition_range_.end()) {
- return ui::Range::InvalidRange();
+ return gfx::Range::InvalidRange();
}
- return ui::Range(
+ return gfx::Range(
request_range.start() - composition_range_.start(),
request_range.end() - composition_range_.start());
}
@@ -1578,16 +1583,16 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
"RenderWidgetHostViewMac::GetFirstRectForCharacterRange");
// If requested range is same as caret location, we can just return it.
- if (selection_range_.is_empty() && ui::Range(range) == selection_range_) {
+ if (selection_range_.is_empty() && gfx::Range(range) == selection_range_) {
if (actual_range)
*actual_range = range;
*rect = NSRectFromCGRect(caret_rect_.ToCGRect());
return true;
}
- const ui::Range request_range_in_composition =
- ConvertCharacterRangeToCompositionRange(ui::Range(range));
- if (request_range_in_composition == ui::Range::InvalidRange())
+ const gfx::Range request_range_in_composition =
+ ConvertCharacterRangeToCompositionRange(gfx::Range(range));
+ if (request_range_in_composition == gfx::Range::InvalidRange())
return false;
// If firstRectForCharacterRange in WebFrame is failed in renderer,
@@ -1596,12 +1601,12 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
return false;
DCHECK_EQ(composition_bounds_.size(), composition_range_.length());
- ui::Range ui_actual_range;
+ gfx::Range ui_actual_range;
*rect = NSRectFromCGRect(GetFirstRectForCompositionRange(
request_range_in_composition,
&ui_actual_range).ToCGRect());
if (actual_range) {
- *actual_range = ui::Range(
+ *actual_range = gfx::Range(
composition_range_.start() + ui_actual_range.start(),
composition_range_.start() + ui_actual_range.end()).ToNSRange();
}
@@ -1787,6 +1792,10 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() {
// Also note that it is necessary that clearDrawable be called if
// overlapping views are not allowed, e.g, for content shell.
// http://crbug.com/178408
+ // Disable screen updates so that the changes of flashes is minimized.
+ // http://crbug.com/279472
+ if (!use_core_animation_)
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
if (allow_overlapping_views_)
DestroyCompositedIOSurfaceAndLayer(kLeaveContextBoundToView);
else
@@ -1853,8 +1862,8 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
render_widget_host_->GetRoutingID(), background));
}
-void RenderWidgetHostViewMac::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewMac::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
if (!GetBrowserAccessibilityManager()) {
SetBrowserAccessibilityManager(
new BrowserAccessibilityManagerMac(
@@ -1862,7 +1871,7 @@ void RenderWidgetHostViewMac::OnAccessibilityNotifications(
BrowserAccessibilityManagerMac::GetEmptyDocument(),
NULL));
}
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
@@ -2325,7 +2334,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
if (textToBeInserted_.length() >
((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
widgetHost->ImeConfirmComposition(
- textToBeInserted_, ui::Range::InvalidRange(), false);
+ textToBeInserted_, gfx::Range::InvalidRange(), false);
textInserted = YES;
}
@@ -2342,7 +2351,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
} else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
if (unmarkTextCalled_) {
widgetHost->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
} else {
widgetHost->ImeCancelComposition();
}
@@ -3422,7 +3431,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// called in keyEvent: method.
if (!handlingKeyDown_) {
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
} else {
unmarkTextCalled_ = YES;
}
@@ -3515,7 +3524,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (handlingKeyDown_) {
textToBeInserted_.append(base::SysNSStringToUTF16(im_text));
} else {
- ui::Range replacement_range(replacementRange);
+ gfx::Range replacement_range(replacementRange);
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
base::SysNSStringToUTF16(im_text), replacement_range, false);
}
@@ -3660,7 +3669,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (renderWidgetHostView_->render_widget_host_)
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), ui::Range::InvalidRange(), false);
+ string16(), gfx::Range::InvalidRange(), false);
[self cancelComposition];
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 0d3ee0a8aa0..ba92843ebf7 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -78,7 +78,7 @@ class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id),
+ : RenderWidgetHostImpl(delegate, process, routing_id, false),
edit_command_message_count_(0) {
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 3c91bc6abdf..7a152d18da8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -101,7 +101,7 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id) {
+ : RenderWidgetHostImpl(delegate, process, routing_id, false) {
}
MOCK_METHOD0(Focus, void());
@@ -140,7 +140,7 @@ void GenerateCompositionRectArray(const gfx::Point& origin,
gfx::Rect GetExpectedRect(const gfx::Point& origin,
const gfx::Size& size,
- const ui::Range& range,
+ const gfx::Range& range,
int line_no) {
return gfx::Rect(
origin.x() + range.start() * size.width(),
@@ -264,7 +264,7 @@ TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape) {
new MockRenderProcessHost(&browser_context);
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
- &delegate, process_host, MSG_ROUTING_NONE);
+ &delegate, process_host, MSG_ROUTING_NONE, false);
RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
RenderWidgetHostView::CreateViewForWidget(rwh));
@@ -298,7 +298,7 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
new MockRenderProcessHost(&browser_context);
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
- &delegate, process_host, MSG_ROUTING_NONE);
+ &delegate, process_host, MSG_ROUTING_NONE, false);
RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
RenderWidgetHostView::CreateViewForWidget(rwh));
@@ -322,7 +322,7 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
const size_t kDummyOffset = 0;
gfx::Rect caret_rect(10, 11, 0, 10);
- ui::Range caret_range(0, 0);
+ gfx::Range caret_range(0, 0);
ViewHostMsg_SelectionBounds_Params params;
NSRect rect;
@@ -336,24 +336,24 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
&rect,
&actual_range));
EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect)));
- EXPECT_EQ(caret_range, ui::Range(actual_range));
+ EXPECT_EQ(caret_range, gfx::Range(actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 3).ToNSRange(),
+ gfx::Range(2, 3).ToNSRange(),
&rect,
&actual_range));
// Caret moved.
caret_rect = gfx::Rect(20, 11, 0, 10);
- caret_range = ui::Range(1, 1);
+ caret_range = gfx::Range(1, 1);
params.anchor_rect = params.focus_rect = caret_rect;
rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
rwhv_mac_->SelectionBoundsChanged(params);
@@ -362,45 +362,45 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
&rect,
&actual_range));
EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect)));
- EXPECT_EQ(caret_range, ui::Range(actual_range));
+ EXPECT_EQ(caret_range, gfx::Range(actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 3).ToNSRange(),
+ gfx::Range(2, 3).ToNSRange(),
&rect,
&actual_range));
// No caret.
- caret_range = ui::Range(1, 2);
+ caret_range = gfx::Range(1, 2);
rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
params.anchor_rect = caret_rect;
params.focus_rect = gfx::Rect(30, 11, 0, 10);
rwhv_mac_->SelectionBoundsChanged(params);
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 2).ToNSRange(),
+ gfx::Range(2, 2).ToNSRange(),
&rect,
&actual_range));
}
@@ -412,46 +412,46 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) {
NSRect rect;
// Make sure not crashing by passing NULL pointer instead of |actual_range|.
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
NULL));
// If there are no update from renderer, always returned caret position.
NSRange actual_range;
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 1).ToNSRange(),
+ gfx::Range(0, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 0).ToNSRange(),
+ gfx::Range(1, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
// If the firstRectForCharacterRange is failed in renderer, empty rect vector
// is sent. Make sure this does not crash.
- rwhv_mac_->ImeCompositionRangeChanged(ui::Range(10, 12),
+ rwhv_mac_->ImeCompositionRangeChanged(gfx::Range(10, 12),
std::vector<gfx::Rect>());
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(10, 11).ToNSRange(),
+ gfx::Range(10, 11).ToNSRange(),
&rect,
NULL));
const int kCompositionLength = 10;
std::vector<gfx::Rect> composition_bounds;
const int kCompositionStart = 3;
- const ui::Range kCompositionRange(kCompositionStart,
+ const gfx::Range kCompositionRange(kCompositionStart,
kCompositionStart + kCompositionLength);
GenerateCompositionRectArray(kOrigin,
kBoundsUnit,
@@ -462,45 +462,45 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) {
// Out of range requests will return caret position.
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(0, 0).ToNSRange(),
+ gfx::Range(0, 0).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 1).ToNSRange(),
+ gfx::Range(1, 1).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(1, 2).ToNSRange(),
+ gfx::Range(1, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(2, 2).ToNSRange(),
+ gfx::Range(2, 2).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(13, 14).ToNSRange(),
+ gfx::Range(13, 14).ToNSRange(),
&rect,
&actual_range));
EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
- ui::Range(14, 15).ToNSRange(),
+ gfx::Range(14, 15).ToNSRange(),
&rect,
&actual_range));
for (int i = 0; i <= kCompositionLength; ++i) {
for (int j = 0; j <= kCompositionLength - i; ++j) {
- const ui::Range range(i, i + j);
+ const gfx::Range range(i, i + j);
const gfx::Rect expected_rect = GetExpectedRect(kOrigin,
kBoundsUnit,
range,
0);
- const NSRange request_range = ui::Range(
+ const NSRange request_range = gfx::Range(
kCompositionStart + range.start(),
kCompositionStart + range.end()).ToNSRange();
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
request_range,
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(request_range), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(request_range), gfx::Range(actual_range));
EXPECT_EQ(expected_rect, gfx::Rect(NSRectToCGRect(rect)));
// Make sure not crashing by passing NULL pointer instead of
@@ -520,7 +520,7 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) {
const int kCompositionLength = 30;
std::vector<gfx::Rect> composition_bounds;
- const ui::Range kCompositionRange(0, kCompositionLength);
+ const gfx::Range kCompositionRange(0, kCompositionLength);
// Set breaking point at 10 and 20.
std::vector<size_t> break_points;
break_points.push_back(10);
@@ -533,113 +533,113 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) {
rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds);
// Range doesn't contain line breaking point.
- ui::Range range;
- range = ui::Range(5, 8);
+ gfx::Range range;
+ range = gfx::Range(5, 8);
NSRange actual_range;
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
GetExpectedRect(kOrigin, kBoundsUnit, range, 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(15, 18);
+ range = gfx::Range(15, 18);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 8), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(25, 28);
+ range = gfx::Range(25, 28);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(range, ui::Range(actual_range));
+ EXPECT_EQ(range, gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 8), 2),
gfx::Rect(NSRectToCGRect(rect)));
// Range contains line breaking point.
- range = ui::Range(8, 12);
+ range = gfx::Range(8, 12);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(8, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(8, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 0),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(8, 10), 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(18, 22);
+ range = gfx::Range(18, 22);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(18, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(18, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(8, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
// Start point is line breaking point.
- range = ui::Range(10, 12);
+ range = gfx::Range(10, 12);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 12), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 12), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 2), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(20, 22);
+ range = gfx::Range(20, 22);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(20, 22), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(20, 22), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 2), 2),
gfx::Rect(NSRectToCGRect(rect)));
// End point is line breaking point.
- range = ui::Range(5, 10);
+ range = gfx::Range(5, 10);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(5, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(5, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 0),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 10), 0),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(15, 20);
+ range = gfx::Range(15, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(15, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(15, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(5, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
// Start and end point are same line breaking point.
- range = ui::Range(10, 10);
+ range = gfx::Range(10, 10);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 10), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 10), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 0), 1),
gfx::Rect(NSRectToCGRect(rect)));
- range = ui::Range(20, 20);
+ range = gfx::Range(20, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(20, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(20, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 2),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 0), 2),
gfx::Rect(NSRectToCGRect(rect)));
// Start and end point are different line breaking point.
- range = ui::Range(10, 20);
+ range = gfx::Range(10, 20);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(),
&rect,
&actual_range));
- EXPECT_EQ(ui::Range(10, 20), ui::Range(actual_range));
+ EXPECT_EQ(gfx::Range(10, 20), gfx::Range(actual_range));
EXPECT_EQ(
- GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 10), 1),
+ GetExpectedRect(kOrigin, kBoundsUnit, gfx::Range(0, 10), 1),
gfx::Rect(NSRectToCGRect(rect)));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win.cc b/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
index a6ee28b0189..de2aa656a0d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -12,8 +12,9 @@
#include <map>
#include <stack>
+#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/i18n/rtl.h"
@@ -56,25 +57,26 @@
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/win/imm32_manager.h"
#include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/text/text_elider.h"
+#include "ui/base/sequential_id_generator.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/touch/touch_enabled.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/view_prop.h"
-#include "ui/base/win/dpi.h"
-#include "ui/base/win/hwnd_util.h"
#include "ui/base/win/mouse_wheel_util.h"
#include "ui/base/win/touch_input.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/hwnd_util.h"
#include "webkit/common/cursors/webcursor.h"
#include "win8/util/win8_util.h"
@@ -312,7 +314,7 @@ void GetScreenInfoForWindow(gfx::NativeViewId id,
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
- if (!GetMonitorInfo(monitor, &monitor_info))
+ if (!base::win::GetMonitorInfoWrapper(monitor, &monitor_info))
return;
DEVMODE dev_mode;
@@ -323,7 +325,7 @@ void GetScreenInfoForWindow(gfx::NativeViewId id,
WebKit::WebScreenInfo screen_info;
screen_info.depth = dev_mode.dmBitsPerPel;
screen_info.depthPerComponent = dev_mode.dmBitsPerPel / 3; // Assumes RGB
- screen_info.deviceScaleFactor = ui::win::GetDeviceScaleFactor();
+ screen_info.deviceScaleFactor = gfx::win::GetDeviceScaleFactor();
screen_info.isMonochrome = dev_mode.dmColor == DMCOLOR_MONOCHROME;
screen_info.rect = gfx::Rect(monitor_info.rcMonitor);
screen_info.availableRect = gfx::Rect(monitor_info.rcWork);
@@ -355,8 +357,6 @@ class WebTouchState {
bool is_changed() { return touch_event_.changedTouchesLength != 0; }
private:
- typedef std::map<unsigned int, int> MapType;
-
// Adds a touch point or returns NULL if there's not enough space.
WebKit::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input);
@@ -374,9 +374,7 @@ class WebTouchState {
WebKit::WebTouchEvent touch_event_;
const RenderWidgetHostViewWin* const window_;
- // Maps OS touch Id's into an internal (WebKit-friendly) touch-id.
- // WebKit expects small consecutive integers, starting at 0.
- MapType touch_map_;
+ ui::SequentialIDGenerator id_generator_;
DISALLOW_COPY_AND_ASSIGN(WebTouchState);
};
@@ -395,7 +393,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
imm32_manager_(new ui::IMM32Manager),
ime_notification_(false),
capture_enter_key_(false),
- is_hidden_(false),
+ is_hidden_(render_widget_host_->is_hidden()),
about_to_validate_and_paint_(false),
close_on_deactivate_(false),
being_destroyed_(false),
@@ -408,7 +406,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
can_compose_inline_(true),
is_fullscreen_(false),
ignore_mouse_movement_(true),
- composition_range_(ui::Range::InvalidRange()),
+ composition_range_(gfx::Range::InvalidRange()),
touch_state_(new WebTouchState(this)),
pointer_down_context_(false),
last_touch_location_(-1, -1),
@@ -450,7 +448,7 @@ void RenderWidgetHostViewWin::InitAsFullscreen(
gfx::Rect pos = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
reference_host_view->GetNativeView()).bounds();
is_fullscreen_ = true;
- DoPopupOrFullscreenInit(ui::GetWindowToParentTo(true), pos, 0);
+ DoPopupOrFullscreenInit(gfx::GetWindowToParentTo(true), pos, 0);
}
RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const {
@@ -501,7 +499,7 @@ void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) {
}
void RenderWidgetHostViewWin::SetBounds(const gfx::Rect& rect) {
- if (is_hidden_)
+ if (being_destroyed_)
return;
// No SWP_NOREDRAW as autofill popups can move and the underneath window
@@ -574,7 +572,7 @@ void RenderWidgetHostViewWin::CleanupCompositorWindow() {
if (!compositor_host_window_)
return;
- ui::SetWindowUserData(compositor_host_window_, NULL);
+ gfx::SetWindowUserData(compositor_host_window_, NULL);
// Hide the compositor and parent it to the desktop rather than destroying
// it immediately. The GPU process has a grace period to stop accessing the
@@ -625,7 +623,7 @@ void RenderWidgetHostViewWin::Show() {
}
void RenderWidgetHostViewWin::Hide() {
- if (!is_fullscreen_ && GetParent() == ui::GetWindowToParentTo(true)) {
+ if (!is_fullscreen_ && GetParent() == gfx::GetWindowToParentTo(true)) {
LOG(WARNING) << "Hide() called twice in a row: " << this << ":"
<< GetParent();
return;
@@ -643,7 +641,7 @@ bool RenderWidgetHostViewWin::IsShowing() {
}
gfx::Rect RenderWidgetHostViewWin::GetViewBounds() const {
- return ui::win::ScreenToDIPRect(GetPixelBounds());
+ return gfx::win::ScreenToDIPRect(GetPixelBounds());
}
gfx::Rect RenderWidgetHostViewWin::GetPixelBounds() const {
@@ -690,8 +688,8 @@ void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) {
void RenderWidgetHostViewWin::TextInputTypeChanged(
ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) {
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
if (text_input_type_ != type ||
text_input_mode_ != input_mode ||
can_compose_inline_ != can_compose_inline) {
@@ -725,7 +723,7 @@ void RenderWidgetHostViewWin::ImeCancelComposition() {
}
void RenderWidgetHostViewWin::ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
composition_range_ = range;
composition_character_bounds_ = character_bounds;
@@ -762,6 +760,7 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
const gfx::Vector2d& scroll_delta,
const std::vector<gfx::Rect>& copy_rects,
const ui::LatencyInfo& latency_info) {
+ TRACE_EVENT0("content", "RenderWidgetHostViewWin::DidUpdateBackingStore");
software_latency_info_.MergeWith(latency_info);
if (is_hidden_)
return;
@@ -772,7 +771,7 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
// surprisingly, this ordering matters.
for (size_t i = 0; i < copy_rects.size(); ++i) {
- gfx::Rect pixel_rect = ui::win::DIPToScreenRect(copy_rects[i]);
+ gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(copy_rects[i]);
// Damage might not be DIP aligned.
pixel_rect.Inset(-1, -1);
RECT bounds = pixel_rect.ToRECT();
@@ -780,11 +779,12 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
}
if (!scroll_rect.IsEmpty()) {
- gfx::Rect pixel_rect = ui::win::DIPToScreenRect(scroll_rect);
+ TRACE_EVENT0("content", "ScrollWindowEx");
+ gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(scroll_rect);
// Damage might not be DIP aligned.
pixel_rect.Inset(-1, -1);
RECT clip_rect = pixel_rect.ToRECT();
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
int dx = static_cast<int>(scale * scroll_delta.x());
int dy = static_cast<int>(scale * scroll_delta.y());
ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
@@ -806,7 +806,7 @@ bool RenderWidgetHostViewWin::CanSubscribeFrame() const {
void RenderWidgetHostViewWin::WillWmDestroy() {
CleanupCompositorWindow();
- if (base::win::IsTSFAwareRequired() && GetFocus() == m_hWnd)
+ if (base::win::IsTSFAwareRequired())
ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
}
@@ -843,7 +843,7 @@ void RenderWidgetHostViewWin::SetTooltipText(const string16& tooltip_text) {
// accidentally DOS the user with a mega tooltip (since Windows doesn't seem
// to do this itself).
const string16 new_tooltip_text =
- ui::TruncateString(tooltip_text, kMaxTooltipLength);
+ gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (new_tooltip_text != tooltip_text_) {
tooltip_text_ = new_tooltip_text;
@@ -883,7 +883,7 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurface(
if (dst_size.IsEmpty() || src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
accelerated_surface_->AsyncCopyTo(src_subrect, dst_size, callback);
}
@@ -902,7 +902,7 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurfaceToVideoFrame(
if (src_subrect.IsEmpty())
return;
- scoped_callback_runner.Release();
+ ignore_result(scoped_callback_runner.Release());
accelerated_surface_->AsyncCopyToVideoFrame(src_subrect, target, callback);
}
@@ -1018,7 +1018,7 @@ void RenderWidgetHostViewWin::InsertText(const string16& text) {
}
if (render_widget_host_)
render_widget_host_->ImeConfirmComposition(text,
- ui::Range::InvalidRange(),
+ gfx::Range::InvalidRange(),
false);
}
@@ -1048,7 +1048,7 @@ ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const {
NOTREACHED();
return ui::TEXT_INPUT_MODE_DEFAULT;
}
- return ui::TEXT_INPUT_MODE_DEFAULT;
+ return text_input_mode_;
}
bool RenderWidgetHostViewWin::CanComposeInline() const {
@@ -1096,7 +1096,7 @@ bool RenderWidgetHostViewWin::HasCompositionText() {
return false;
}
-bool RenderWidgetHostViewWin::GetTextRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1106,7 +1106,7 @@ bool RenderWidgetHostViewWin::GetTextRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetCompositionTextRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1116,7 +1116,7 @@ bool RenderWidgetHostViewWin::GetCompositionTextRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetSelectionRange(ui::Range* range) {
+bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1126,7 +1126,7 @@ bool RenderWidgetHostViewWin::GetSelectionRange(ui::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::SetSelectionRange(const ui::Range& range) {
+bool RenderWidgetHostViewWin::SetSelectionRange(const gfx::Range& range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1136,7 +1136,7 @@ bool RenderWidgetHostViewWin::SetSelectionRange(const ui::Range& range) {
return false;
}
-bool RenderWidgetHostViewWin::DeleteRange(const ui::Range& range) {
+bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1146,13 +1146,13 @@ bool RenderWidgetHostViewWin::DeleteRange(const ui::Range& range) {
return false;
}
-bool RenderWidgetHostViewWin::GetTextFromRange(const ui::Range& range,
+bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range,
string16* text) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
}
- ui::Range selection_text_range(selection_text_offset_,
+ gfx::Range selection_text_range(selection_text_offset_,
selection_text_offset_ + selection_text_.length());
if (!selection_text_range.Contains(range)) {
text->clear();
@@ -1313,7 +1313,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
if (backing_store) {
gfx::Rect bitmap_rect(gfx::Point(),
- ui::win::DIPToScreenSize(backing_store->size()));
+ gfx::win::DIPToScreenSize(backing_store->size()));
bool manage_colors = BackingStoreWin::ColorManagementEnabled();
if (manage_colors)
@@ -1667,7 +1667,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
ui::CompositionText composition;
if (imm32_manager_->GetResult(m_hWnd, lparam, &composition.text)) {
render_widget_host_->ImeConfirmComposition(
- composition.text, ui::Range::InvalidRange(), false);
+ composition.text, gfx::Range::InvalidRange(), false);
imm32_manager_->ResetComposition(m_hWnd);
// Fall though and try reading the composition string.
// Japanese IMEs send a message containing both GCS_RESULTSTR and
@@ -1679,7 +1679,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
if (imm32_manager_->GetComposition(m_hWnd, lparam, &composition)) {
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
- composition.selection = ui::Range(composition.selection.end());
+ composition.selection = gfx::Range(composition.selection.end());
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
@@ -2001,7 +2001,7 @@ LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
if (render_widget_host_) {
WebKit::WebMouseWheelEvent wheel_event =
WebMouseWheelEventBuilder::Build(m_hWnd, message, wparam, lparam);
- float scale = ui::win::GetDeviceScaleFactor();
+ float scale = gfx::win::GetDeviceScaleFactor();
wheel_event.x /= scale;
wheel_event.y /= scale;
wheel_event.deltaX /= scale;
@@ -2014,7 +2014,9 @@ LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
}
WebTouchState::WebTouchState(const RenderWidgetHostViewWin* window)
- : window_(window) { }
+ : window_(window),
+ id_generator_(0) {
+}
size_t WebTouchState::UpdateTouchPoints(
TOUCHINPUT* points, size_t count) {
@@ -2114,22 +2116,12 @@ size_t WebTouchState::UpdateTouchPoints(
}
void WebTouchState::RemoveExpiredMappings() {
- WebTouchState::MapType new_map;
- for (MapType::iterator it = touch_map_.begin();
- it != touch_map_.end();
- ++it) {
- WebKit::WebTouchPoint* point = touch_event_.touches;
- WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
- while (point < end) {
- if ((point->id == it->second) &&
- (point->state != WebKit::WebTouchPoint::StateReleased)) {
- new_map.insert(*it);
- break;
- }
- point++;
- }
+ WebKit::WebTouchPoint* point = touch_event_.touches;
+ WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
+ for (; point < end; ++point) {
+ if (point->state == WebKit::WebTouchPoint::StateReleased)
+ id_generator_.ReleaseGeneratedID(point->id);
}
- touch_map_.swap(new_map);
}
@@ -2167,18 +2159,20 @@ bool WebTouchState::UpdateTouchPoint(
WebKit::WebTouchPoint* touch_point,
TOUCHINPUT* touch_input) {
CPoint coordinates(
- TOUCH_COORD_TO_PIXEL(touch_input->x) / ui::win::GetUndocumentedDPIScale(),
- TOUCH_COORD_TO_PIXEL(touch_input->y) / ui::win::GetUndocumentedDPIScale());
+ TOUCH_COORD_TO_PIXEL(touch_input->x) /
+ gfx::win::GetUndocumentedDPITouchScale(),
+ TOUCH_COORD_TO_PIXEL(touch_input->y) /
+ gfx::win::GetUndocumentedDPITouchScale());
int radius_x = 1;
int radius_y = 1;
if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) {
// Some touch drivers send a contact area of "-1", yet flag it as valid.
radius_x = std::max(1,
static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cxContact) /
- ui::win::GetUndocumentedDPIScale()));
+ gfx::win::GetUndocumentedDPITouchScale()));
radius_y = std::max(1,
static_cast<int>(TOUCH_COORD_TO_PIXEL(touch_input->cyContact) /
- ui::win::GetUndocumentedDPIScale()));
+ gfx::win::GetUndocumentedDPITouchScale()));
}
// Detect and exclude stationary moves.
@@ -2194,7 +2188,7 @@ bool WebTouchState::UpdateTouchPoint(
touch_point->screenPosition.x = coordinates.x;
touch_point->screenPosition.y = coordinates.y;
window_->ScreenToClient(&coordinates);
- static float scale = ui::win::GetDeviceScaleFactor();
+ static float scale = gfx::win::GetDeviceScaleFactor();
touch_point->position.x = coordinates.x / scale;
touch_point->position.y = coordinates.y / scale;
touch_point->radiusX = radius_x;
@@ -2206,14 +2200,7 @@ bool WebTouchState::UpdateTouchPoint(
// Find (or create) a mapping for _os_touch_id_.
unsigned int WebTouchState::GetMappedTouch(unsigned int os_touch_id) {
- MapType::iterator it = touch_map_.find(os_touch_id);
- if (it != touch_map_.end())
- return it->second;
- int next_value = 0;
- for (it = touch_map_.begin(); it != touch_map_.end(); ++it)
- next_value = std::max(next_value, it->second + 1);
- touch_map_[os_touch_id] = next_value;
- return next_value;
+ return id_generator_.GetGeneratedID(os_touch_id);
}
LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
@@ -2241,8 +2228,10 @@ LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
if (total == 1 && (points[0].dwFlags & TOUCHEVENTF_DOWN)) {
pointer_down_context_ = true;
last_touch_location_ = gfx::Point(
- TOUCH_COORD_TO_PIXEL(points[0].x) / ui::win::GetUndocumentedDPIScale(),
- TOUCH_COORD_TO_PIXEL(points[0].y) / ui::win::GetUndocumentedDPIScale());
+ TOUCH_COORD_TO_PIXEL(points[0].x) /
+ gfx::win::GetUndocumentedDPITouchScale(),
+ TOUCH_COORD_TO_PIXEL(points[0].y) /
+ gfx::win::GetUndocumentedDPITouchScale());
}
bool should_forward = render_widget_host_->ShouldForwardTouchEvent() &&
@@ -2311,7 +2300,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 (ui::GetClassName(child_window) == kWrapperNativeWindowClassName)
+ if (gfx::GetClassName(child_window) == kWrapperNativeWindowClassName)
child_window = ::GetWindow(child_window, GW_CHILD);
::SetFocus(child_window);
@@ -2372,10 +2361,10 @@ LRESULT RenderWidgetHostViewWin::OnMoveOrSize(
return 0;
}
-void RenderWidgetHostViewWin::OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
+void RenderWidgetHostViewWin::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) {
CreateBrowserAccessibilityManagerIfNeeded();
- GetBrowserAccessibilityManager()->OnAccessibilityNotifications(params);
+ GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
bool RenderWidgetHostViewWin::LockMouse() {
@@ -2457,7 +2446,7 @@ static void PaintCompositorHostWindow(HWND hWnd) {
BeginPaint(hWnd, &paint);
RenderWidgetHostViewWin* win = static_cast<RenderWidgetHostViewWin*>(
- ui::GetWindowUserData(hWnd));
+ gfx::GetWindowUserData(hWnd));
// Trigger composite to rerender window.
if (win)
win->AcceleratedPaint(paint.hdc);
@@ -2506,7 +2495,7 @@ gfx::Rect RenderWidgetHostViewWin::GetBoundsInRootWindow() {
GetSystemMetrics(SM_CYSIZEFRAME));
}
- return ui::win::ScreenToDIPRect(rect);
+ return gfx::win::ScreenToDIPRect(rect);
}
// Creates a HWND within the RenderWidgetHostView that will serve as a host
@@ -2556,9 +2545,9 @@ gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() {
MAKEINTATOM(atom), 0,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
0, 0, width, height, m_hWnd, 0, instance, 0);
- ui::CheckWindowCreated(compositor_host_window_);
+ gfx::CheckWindowCreated(compositor_host_window_);
- ui::SetWindowUserData(compositor_host_window_, this);
+ gfx::SetWindowUserData(compositor_host_window_, this);
gfx::GLSurfaceHandle surface_handle(compositor_host_window_,
gfx::NATIVE_TRANSPORT);
@@ -2754,6 +2743,8 @@ void RenderWidgetHostViewWin::OnFinalMessage(HWND window) {
}
if (render_widget_host_)
render_widget_host_->ViewDestroyed();
+ if (base::win::IsTSFAwareRequired())
+ ui::TSFBridge::GetInstance()->RemoveFocusedClient(this);
delete this;
}
@@ -2887,7 +2878,7 @@ void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
return;
}
- gfx::Point point = ui::win::ScreenToDIPPoint(
+ gfx::Point point = gfx::win::ScreenToDIPPoint(
gfx::Point(static_cast<short>(LOWORD(lparam)),
static_cast<short>(HIWORD(lparam))));
lparam = MAKELPARAM(point.x(), point.y());
@@ -2966,7 +2957,7 @@ void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd,
const gfx::Rect& pos,
DWORD ex_style) {
Create(parent_hwnd, NULL, NULL, WS_POPUP, ex_style);
- gfx::Rect screen_rect = ui::win::DIPToScreenRect(pos);
+ gfx::Rect screen_rect = gfx::win::DIPToScreenRect(pos);
MoveWindow(screen_rect.x(), screen_rect.y(), screen_rect.width(),
screen_rect.height(), TRUE);
ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
@@ -3180,7 +3171,7 @@ void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary(
return;
ui::tsf_inputscope::SetInputScopeForTsfUnawareWindow(
- m_hWnd, text_input_type, ui::TEXT_INPUT_MODE_DEFAULT);
+ m_hWnd, text_input_type, text_input_mode_);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win.h b/chromium/content/browser/renderer_host/render_widget_host_view_win.h
index 52030d78f39..6650ae4ba8b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_win.h
@@ -182,14 +182,14 @@ class RenderWidgetHostViewWin
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
virtual void SetIsLoading(bool is_loading) OVERRIDE;
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE;
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE;
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
virtual void ScrollOffsetChanged() OVERRIDE;
virtual void ImeCancelComposition() OVERRIDE;
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect,
@@ -233,8 +233,8 @@ class RenderWidgetHostViewWin
virtual void AcceleratedSurfaceSuspend() OVERRIDE;
virtual void AcceleratedSurfaceRelease() OVERRIDE;
virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>& params
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params
) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
@@ -277,12 +277,12 @@ class RenderWidgetHostViewWin
virtual bool GetCompositionCharacterBounds(uint32 index,
gfx::Rect* rect) OVERRIDE;
virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(ui::Range* range) OVERRIDE;
- virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE;
- virtual bool DeleteRange(const ui::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const ui::Range& range,
+ virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE;
+ virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
+ virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
+ virtual bool GetTextFromRange(const gfx::Range& range,
string16* text) OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
@@ -572,7 +572,7 @@ class RenderWidgetHostViewWin
// back, we regard the mouse movement as (0, 0).
bool ignore_mouse_movement_;
- ui::Range composition_range_;
+ gfx::Range composition_range_;
// The current composition character bounds.
std::vector<gfx::Rect> composition_character_bounds_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
index 76070bc70e5..fc73601fb6c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
@@ -10,11 +10,11 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
-#include "content/public/test/test_utils.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/shell/shell.h"
-#include "content/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ime/win/imm32_manager.h"
@@ -87,16 +87,16 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinBrowserTest,
MockIMM32Manager* mock = new MockIMM32Manager();
mock->Reset();
view_->imm32_manager_.reset(mock);
- view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
- ui::TEXT_INPUT_MODE_EMAIL);
+ view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE,
+ ui::TEXT_INPUT_MODE_EMAIL, false);
EXPECT_EQ(1, mock->call_count());
EXPECT_EQ(view_->m_hWnd, mock->window_handle());
EXPECT_EQ(ui::TEXT_INPUT_MODE_EMAIL, mock->input_mode());
mock->Reset();
- view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
- ui::TEXT_INPUT_MODE_EMAIL);
+ view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE,
+ ui::TEXT_INPUT_MODE_EMAIL, false);
EXPECT_EQ(0, mock->call_count());
}
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc b/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc
deleted file mode 100644
index 2538a188354..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_calculator.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-
-namespace content {
-
-SmoothScrollCalculator::SmoothScrollCalculator() {
-}
-
-SmoothScrollCalculator::~SmoothScrollCalculator() {
-}
-
-double SmoothScrollCalculator::GetScrollDelta(
- base::TimeTicks now, base::TimeDelta desired_interval) {
- double position_delta = 10;
- if (!last_tick_time_.is_null()) {
- double velocity = 10 / desired_interval.InMillisecondsF();
- double time_delta = (now - last_tick_time_).InMillisecondsF();
- position_delta = velocity * time_delta;
- }
-
- last_tick_time_ = now;
- return position_delta;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_calculator.h b/chromium/content/browser/renderer_host/smooth_scroll_calculator.h
deleted file mode 100644
index 1427416be41..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_calculator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_CALCULATOR_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_CALCULATOR_H_
-
-#include "base/time/time.h"
-
-namespace content {
-
-// An utility class to calculate the delta for smooth scroll gesture
-// events.
-class SmoothScrollCalculator {
- public:
- SmoothScrollCalculator();
- ~SmoothScrollCalculator();
-
- double GetScrollDelta(base::TimeTicks now, base::TimeDelta desired_interval);
-
- private:
- base::TimeTicks last_tick_time_;
-
- DISALLOW_COPY_AND_ASSIGN(SmoothScrollCalculator);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_CALCULATOR_H_
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc b/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
deleted file mode 100644
index ca9dfae9b78..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
-
-#include "base/debug/trace_event.h"
-#include "base/message_loop/message_loop.h"
-#include "content/common/view_messages.h"
-#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
-#include "content/public/browser/render_widget_host.h"
-
-namespace content {
-
-namespace {
-
-// How many milliseconds apart synthetic scroll messages should be sent.
-const int kSyntheticScrollMessageIntervalMs = 7;
-
-} // namespace
-
-SmoothScrollGestureController::SmoothScrollGestureController()
- : rwh_(NULL) {
-}
-
-SmoothScrollGestureController::~SmoothScrollGestureController() {
-}
-
-void SmoothScrollGestureController::BeginSmoothScroll(
- RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params) {
- if (pending_smooth_scroll_gesture_.get())
- return;
-
- rwh_ = view->GetRenderWidgetHost();
- pending_smooth_scroll_gesture_ = view->CreateSmoothScrollGesture(
- params.scroll_down,
- params.pixels_to_scroll,
- params.mouse_event_x,
- params.mouse_event_y);
-
- timer_.Start(FROM_HERE, GetSyntheticScrollMessageInterval(), this,
- &SmoothScrollGestureController::OnTimer);
-}
-
-base::TimeDelta
- SmoothScrollGestureController::GetSyntheticScrollMessageInterval() const {
- return base::TimeDelta::FromMilliseconds(kSyntheticScrollMessageIntervalMs);
-}
-
-void SmoothScrollGestureController::OnTimer() {
- base::TimeTicks now = base::TimeTicks::Now();
- if (!pending_smooth_scroll_gesture_->ForwardInputEvents(now, rwh_)) {
- timer_.Stop();
- pending_smooth_scroll_gesture_ = NULL;
- rwh_->Send(new ViewMsg_SmoothScrollCompleted(rwh_->GetRoutingID()));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h b/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h
deleted file mode 100644
index 1477a171e6a..00000000000
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
-
-#include <map>
-
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-
-struct ViewHostMsg_BeginSmoothScroll_Params;
-
-namespace content {
-
-class RenderWidgetHost;
-class RenderWidgetHostViewPort;
-class SmoothScrollGesture;
-
-// Controls SmoothScrollGestures, used to inject synthetic events
-// for performance test harness.
-class CONTENT_EXPORT SmoothScrollGestureController {
- public:
- SmoothScrollGestureController();
- ~SmoothScrollGestureController();
-
- // Initiates a synthetic event stream.
- void BeginSmoothScroll(RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params);
-
- base::TimeDelta GetSyntheticScrollMessageInterval() const;
-
- private:
- // Called periodically to advance the active scroll gesture after being
- // initiated by OnBeginSmoothScroll.
- void OnTimer();
-
- base::RepeatingTimer<SmoothScrollGestureController> timer_;
-
- RenderWidgetHost* rwh_;
-
- scoped_refptr<SmoothScrollGesture> pending_smooth_scroll_gesture_;
-
- DISALLOW_COPY_AND_ASSIGN(SmoothScrollGestureController);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
index 7f122df2c73..677c281932c 100644
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
@@ -30,14 +30,13 @@ const size_t kMaxSocketStreamHosts = 16 * 1024;
SocketStreamDispatcherHost::SocketStreamDispatcherHost(
int render_process_id,
- ResourceMessageFilter::URLRequestContextSelector* selector,
+ const GetRequestContextCallback& request_context_callback,
ResourceContext* resource_context)
: render_process_id_(render_process_id),
- url_request_context_selector_(selector),
+ request_context_callback_(request_context_callback),
resource_context_(resource_context),
weak_ptr_factory_(this),
on_shutdown_(false) {
- DCHECK(selector);
net::WebSocketJob::EnsureInit();
}
@@ -263,8 +262,7 @@ void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id) {
}
net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
- return url_request_context_selector_->GetRequestContext(
- ResourceType::SUB_RESOURCE);
+ return request_context_callback_.Run(ResourceType::SUB_RESOURCE);
}
void SocketStreamDispatcherHost::Shutdown() {
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
index 732923e690f..958eada3a57 100644
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
@@ -7,9 +7,9 @@
#include <vector>
+#include "base/callback_forward.h"
#include "base/id_map.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/public/browser/browser_message_filter.h"
#include "net/socket_stream/socket_stream.h"
@@ -32,9 +32,11 @@ class SocketStreamDispatcherHost
public net::SocketStream::Delegate,
public SSLErrorHandler::Delegate {
public:
+ typedef base::Callback<net::URLRequestContext*(ResourceType::Type)>
+ GetRequestContextCallback;
SocketStreamDispatcherHost(
int render_process_id,
- ResourceMessageFilter::URLRequestContextSelector* selector,
+ const GetRequestContextCallback& request_context_callback,
ResourceContext* resource_context);
// BrowserMessageFilter:
@@ -84,8 +86,7 @@ class SocketStreamDispatcherHost
IDMap<SocketStreamHost> hosts_;
int render_process_id_;
- const scoped_ptr<ResourceMessageFilter::URLRequestContextSelector>
- url_request_context_selector_;
+ GetRequestContextCallback request_context_callback_;
ResourceContext* resource_context_;
base::WeakPtrFactory<SocketStreamDispatcherHost> weak_ptr_factory_;
diff --git a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
index b563480efd9..d382cd57565 100644
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
+++ b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
@@ -15,7 +15,7 @@
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-#include "ui/gl/android/surface_texture_bridge.h"
+#include "ui/gl/android/surface_texture.h"
namespace content {
@@ -26,7 +26,7 @@ static const uint32 kGLTextureExternalOES = 0x8D65;
class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
public:
SurfaceRefAndroid(
- const scoped_refptr<gfx::SurfaceTextureBridge>& surface,
+ const scoped_refptr<gfx::SurfaceTexture>& surface,
ANativeWindow* window)
: surface_(surface),
window_(window) {
@@ -39,7 +39,7 @@ class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
ANativeWindow_release(window_);
}
- scoped_refptr<gfx::SurfaceTextureBridge> surface_;
+ scoped_refptr<gfx::SurfaceTexture> surface_;
ANativeWindow* window_;
};
@@ -61,7 +61,7 @@ scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() {
// Use a SurfaceTexture to stream frames to the UI thread.
video_layer_ = cc::VideoLayer::Create(this);
- surface_texture_ = new gfx::SurfaceTextureBridge(0);
+ surface_texture_ = new gfx::SurfaceTexture(0);
surface_texture_->SetFrameAvailableCallback(
base::Bind(
&SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
diff --git a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
index 83d917552dc..5a000bb246e 100644
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
+++ b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
@@ -21,7 +21,7 @@ class VideoLayer;
}
namespace gfx {
-class SurfaceTextureBridge;
+class SurfaceTexture;
}
namespace content {
@@ -45,7 +45,7 @@ class SurfaceTextureTransportClient : public cc::VideoFrameProvider {
void OnSurfaceTextureFrameAvailable();
scoped_refptr<cc::VideoLayer> video_layer_;
- scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_;
+ scoped_refptr<gfx::SurfaceTexture> surface_texture_;
ANativeWindow* window_;
scoped_refptr<media::VideoFrame> video_frame_;
uint32 texture_id_;
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
new file mode 100644
index 00000000000..9816df93b48
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+
+
+namespace {
+
+const float kDefaultPositionDelta = 10.0f;
+
+}
+
+
+namespace content {
+
+SyntheticGestureCalculator::SyntheticGestureCalculator() {
+}
+
+SyntheticGestureCalculator::~SyntheticGestureCalculator() {
+}
+
+float SyntheticGestureCalculator::GetDelta(
+ base::TimeTicks now, base::TimeDelta desired_interval) {
+ float position_delta = kDefaultPositionDelta;
+ if (!last_tick_time_.is_null()) {
+ float velocity = kDefaultPositionDelta /
+ (float)desired_interval.InMillisecondsF();
+ float time_delta = (now - last_tick_time_).InMillisecondsF();
+ position_delta = velocity * time_delta;
+ }
+
+ last_tick_time_ = now;
+ return position_delta;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h
new file mode 100644
index 00000000000..c2af4978ac4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
+#define CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
+
+#include "base/time/time.h"
+
+namespace content {
+
+// A utility class to calculate the delta for synthetic gesture events.
+class SyntheticGestureCalculator {
+ public:
+ SyntheticGestureCalculator();
+ ~SyntheticGestureCalculator();
+
+ float GetDelta(base::TimeTicks now, base::TimeDelta desired_interval);
+
+ private:
+ base::TimeTicks last_tick_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureCalculator);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc b/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc
new file mode 100644
index 00000000000..46c4329da6b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/synthetic_gesture_controller.h"
+
+#include "base/debug/trace_event.h"
+#include "base/message_loop/message_loop.h"
+#include "content/common/view_messages.h"
+#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/port/browser/synthetic_gesture.h"
+#include "content/public/browser/render_widget_host.h"
+
+namespace content {
+
+namespace {
+
+// How many milliseconds apart synthetic scroll messages should be sent.
+const int kSyntheticGestureMessageIntervalMs = 7;
+
+} // namespace
+
+SyntheticGestureController::SyntheticGestureController()
+ : rwh_(NULL) {
+}
+
+SyntheticGestureController::~SyntheticGestureController() {
+}
+
+void SyntheticGestureController::BeginSmoothScroll(
+ RenderWidgetHostViewPort* view,
+ const ViewHostMsg_BeginSmoothScroll_Params& params) {
+ if (pending_synthetic_gesture_.get())
+ return;
+
+ rwh_ = view->GetRenderWidgetHost();
+ pending_synthetic_gesture_ = view->CreateSmoothScrollGesture(
+ params.scroll_down,
+ params.pixels_to_scroll,
+ params.mouse_event_x,
+ params.mouse_event_y);
+
+ TRACE_EVENT_ASYNC_BEGIN0("benchmark", "SyntheticGestureController::running",
+ pending_synthetic_gesture_);
+ timer_.Start(FROM_HERE, GetSyntheticGestureMessageInterval(), this,
+ &SyntheticGestureController::OnTimer);
+}
+
+void SyntheticGestureController::BeginPinch(
+ RenderWidgetHostViewPort* view,
+ const ViewHostMsg_BeginPinch_Params& params) {
+ if (pending_synthetic_gesture_.get())
+ return;
+
+ rwh_ = view->GetRenderWidgetHost();
+ pending_synthetic_gesture_ = view->CreatePinchGesture(
+ params.zoom_in,
+ params.pixels_to_move,
+ params.anchor_x,
+ params.anchor_y);
+
+ TRACE_EVENT_ASYNC_BEGIN0("benchmark", "SyntheticGestureController::running",
+ pending_synthetic_gesture_);
+ timer_.Start(FROM_HERE, GetSyntheticGestureMessageInterval(), this,
+ &SyntheticGestureController::OnTimer);
+}
+
+base::TimeDelta
+ SyntheticGestureController::GetSyntheticGestureMessageInterval() const {
+ return base::TimeDelta::FromMilliseconds(kSyntheticGestureMessageIntervalMs);
+}
+
+void SyntheticGestureController::OnTimer() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (!pending_synthetic_gesture_->ForwardInputEvents(now, rwh_)) {
+ timer_.Stop();
+ TRACE_EVENT_ASYNC_END0("benchmark", "SyntheticGestureController::running",
+ pending_synthetic_gesture_);
+ pending_synthetic_gesture_ = NULL;
+ rwh_->Send(new ViewMsg_SyntheticGestureCompleted(rwh_->GetRoutingID()));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_controller.h b/chromium/content/browser/renderer_host/synthetic_gesture_controller.h
new file mode 100644
index 00000000000..8826aaddf3a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
+
+#include <map>
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+
+struct ViewHostMsg_BeginPinch_Params;
+struct ViewHostMsg_BeginSmoothScroll_Params;
+
+namespace content {
+
+class RenderWidgetHost;
+class RenderWidgetHostViewPort;
+class SyntheticGesture;
+
+// Controls SyntheticGestures, used to inject synthetic events
+// for performance test harness.
+class CONTENT_EXPORT SyntheticGestureController {
+ public:
+ SyntheticGestureController();
+ ~SyntheticGestureController();
+
+ // Initiates a synthetic event stream to simulate a smooth scroll.
+ void BeginSmoothScroll(RenderWidgetHostViewPort* view,
+ const ViewHostMsg_BeginSmoothScroll_Params& params);
+
+ // Initiates a synthetic event stream to simulate a pinch-to-zoom.
+ void BeginPinch(RenderWidgetHostViewPort* view,
+ const ViewHostMsg_BeginPinch_Params& params);
+
+ base::TimeDelta GetSyntheticGestureMessageInterval() const;
+
+ private:
+ // Called periodically to advance the active scroll gesture after being
+ // initiated by OnBeginSmoothScroll.
+ void OnTimer();
+
+ base::RepeatingTimer<SyntheticGestureController> timer_;
+
+ RenderWidgetHost* rwh_;
+
+ scoped_refptr<SyntheticGesture> pending_synthetic_gesture_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
index 95d26473ee1..7fb9ba9e601 100644
--- a/chromium/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,11 +6,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
+#include "content/browser/renderer_host/synthetic_gesture_controller.h"
#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/port/browser/synthetic_gesture.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,9 +26,9 @@ namespace content {
namespace {
-class MockSmoothScrollGesture : public SmoothScrollGesture {
+class MockSyntheticGesture : public SyntheticGesture {
public:
- MockSmoothScrollGesture() :
+ MockSyntheticGesture() :
called_(0) {
}
@@ -42,7 +42,7 @@ class MockSmoothScrollGesture : public SmoothScrollGesture {
int called_;
protected:
- virtual ~MockSmoothScrollGesture() {
+ virtual ~MockSyntheticGesture() {
}
};
@@ -59,7 +59,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id) {
+ : RenderWidgetHostImpl(delegate, process, routing_id, false) {
}
virtual ~MockRenderWidgetHost() {}
};
@@ -73,10 +73,10 @@ class TestView : public TestRenderWidgetHostView {
virtual ~TestView() {}
// TestRenderWidgetHostView implementation:
- virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+ virtual SyntheticGesture* CreateSmoothScrollGesture(
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
int mouse_event_y) OVERRIDE {
- mock_gesture_ = new MockSmoothScrollGesture();
+ mock_gesture_ = new MockSyntheticGesture();
return mock_gesture_;
}
@@ -84,14 +84,14 @@ class TestView : public TestRenderWidgetHostView {
return rwh_;
}
- MockSmoothScrollGesture* mock_gesture_;
+ MockSyntheticGesture* mock_gesture_;
};
-class SmoothScrollGestureControllerTest : public testing::Test {
+class SyntheticGestureControllerTest : public testing::Test {
public:
- SmoothScrollGestureControllerTest() : process_(NULL) {
+ SyntheticGestureControllerTest() : process_(NULL) {
}
- virtual ~SmoothScrollGestureControllerTest() {}
+ virtual ~SyntheticGestureControllerTest() {}
protected:
// testing::Test implementation:
@@ -131,7 +131,7 @@ class SmoothScrollGestureControllerTest : public testing::Test {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitClosure(),
TimeDelta::FromMilliseconds(
- controller_.GetSyntheticScrollMessageInterval().InMilliseconds() *
+ controller_.GetSyntheticGestureMessageInterval().InMilliseconds() *
3));
base::MessageLoop::current()->Run();
}
@@ -147,10 +147,10 @@ class SmoothScrollGestureControllerTest : public testing::Test {
scoped_ptr<gfx::Screen> screen_;
#endif
- SmoothScrollGestureController controller_;
+ SyntheticGestureController controller_;
};
-TEST_F(SmoothScrollGestureControllerTest, Tick) {
+TEST_F(SyntheticGestureControllerTest, Tick) {
ViewHostMsg_BeginSmoothScroll_Params params;
params.scroll_down = true;
params.pixels_to_scroll = 10;
@@ -168,7 +168,7 @@ TEST_F(SmoothScrollGestureControllerTest, Tick) {
EXPECT_LT(0, current_ticks);
// Ensure it won't start another smooth scroll.
- MockSmoothScrollGesture* original_gesture = view_->mock_gesture_;
+ MockSyntheticGesture* original_gesture = view_->mock_gesture_;
controller_.BeginSmoothScroll(view_.get(), params);
PostQuitMessageAndRun();
EXPECT_EQ(original_gesture, view_->mock_gesture_);
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.cc b/chromium/content/browser/renderer_host/test_render_view_host.cc
index 129591cac7b..caf79cf8583 100644
--- a/chromium/content/browser/renderer_host/test_render_view_host.cc
+++ b/chromium/content/browser/renderer_host/test_render_view_host.cc
@@ -15,7 +15,6 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_client.h"
#include "content/public/common/page_state.h"
-#include "content/public/common/password_form.h"
#include "content/test/test_web_contents.h"
#include "media/base/video_frame.h"
#include "ui/gfx/rect.h"
@@ -42,7 +41,6 @@ void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
params->should_update_history = false;
params->searchable_form_url = GURL();
params->searchable_form_encoding = std::string();
- params->password_form = PasswordForm();
params->security_info = std::string();
params->gesture = NavigationGestureUser;
params->was_within_same_page = false;
@@ -214,14 +212,6 @@ void TestRenderWidgetHostView::SetClickthroughRegion(SkRegion* region) {
}
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
-gfx::NativeViewAccessible
-TestRenderWidgetHostView::AccessibleObjectFromChildId(long child_id) {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif
-
bool TestRenderWidgetHostView::LockMouse() {
return false;
}
@@ -247,7 +237,8 @@ TestRenderViewHost::TestRenderViewHost(
widget_delegate,
routing_id,
main_frame_routing_id,
- swapped_out),
+ swapped_out,
+ false /* hidden */),
render_view_created_(false),
delete_counter_(NULL),
simulate_fetch_via_proxy_(false),
@@ -333,7 +324,6 @@ void TestRenderViewHost::SendNavigateWithParameters(
params.should_update_history = true;
params.searchable_form_url = GURL();
params.searchable_form_encoding = std::string();
- params.password_form = PasswordForm();
params.security_info = std::string();
params.gesture = NavigationGestureUser;
params.contents_mime_type = contents_mime_type_;
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.h b/chromium/content/browser/renderer_host/test_render_view_host.h
index 37b46e2bef8..1eb7583bec0 100644
--- a/chromium/content/browser/renderer_host/test_render_view_host.h
+++ b/chromium/content/browser/renderer_host/test_render_view_host.h
@@ -99,12 +99,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
virtual void SetIsLoading(bool is_loading) OVERRIDE {}
virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE {}
virtual void TextInputTypeChanged(ui::TextInputType type,
- bool can_compose_inline,
- ui::TextInputMode input_mode) OVERRIDE {}
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) OVERRIDE {}
virtual void ImeCancelComposition() OVERRIDE {}
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
virtual void ImeCompositionRangeChanged(
- const ui::Range& range,
+ const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) OVERRIDE {}
#endif
virtual void DidUpdateBackingStore(
@@ -158,17 +158,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
bool has_horizontal_scrollbar) OVERRIDE { }
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE { }
- virtual void OnAccessibilityNotifications(
- const std::vector<AccessibilityHostMsg_NotificationParams>&
- params) OVERRIDE {}
+ virtual void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params) OVERRIDE {}
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
#if defined(OS_WIN) && !defined(USE_AURA)
virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
#endif
-#if defined(OS_WIN) && defined(USE_AURA)
- virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
- OVERRIDE;
-#endif
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
#if defined(OS_WIN) && defined(USE_AURA)
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac.mm b/chromium/content/browser/renderer_host/text_input_client_mac.mm
index cdf56a1eb19..b9d900a704e 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac.mm
@@ -61,7 +61,7 @@ NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(
new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
- ui::Range(range)));
+ gfx::Range(range)));
// http://crbug.com/121917
base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
@@ -82,7 +82,7 @@ NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
BeforeRequest();
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
- ui::Range(range)));
+ gfx::Range(range)));
// http://crbug.com/121917
base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 2a4c6d7f08d..0993018e8f4 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -42,7 +42,7 @@ class TextInputClientMacTest : public testing::Test {
widget_(&delegate_,
process_factory_.CreateRenderProcessHost(
&browser_context_, NULL),
- MSG_ROUTING_NONE),
+ MSG_ROUTING_NONE, false),
thread_("TextInputClientMacTestThread") {}
// Accessor for the TextInputClientMac instance.
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.h b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
index 2a374df5c5e..5a1405ae5ff 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.h
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
@@ -9,11 +9,8 @@
#include "content/public/browser/browser_message_filter.h"
namespace gfx {
-class Rect;
-}
-
-namespace ui {
class Range;
+class Rect;
}
namespace content {
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
index cea0a347d70..7af5a8ff2bd 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
@@ -10,7 +10,7 @@
#include "content/common/text_input_client_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ipc/ipc_message_macros.h"
-#include "ui/base/range/range.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc
deleted file mode 100644
index c504f6c07c9..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_android.h"
-
-#include "base/debug/trace_event.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "jni/SmoothScroller_jni.h"
-
-namespace {
-bool g_jni_initialized = false;
-
-void RegisterNativesIfNeeded(JNIEnv* env) {
- if (!g_jni_initialized) {
- content::RegisterNativesImpl(env);
- g_jni_initialized = true;
- }
-}
-} // namespace
-
-namespace content {
-
-TouchSmoothScrollGestureAndroid::TouchSmoothScrollGestureAndroid(
- int pixels_to_scroll,
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_scroller)
- : pixels_scrolled_(0),
- has_started_(false),
- has_sent_motion_up_(false),
- pixels_to_scroll_(pixels_to_scroll),
- rwh_(rwh),
- java_scroller_(java_scroller) {
- JNIEnv* env = base::android::AttachCurrentThread();
- RegisterNativesIfNeeded(env);
-}
-
-TouchSmoothScrollGestureAndroid::~TouchSmoothScrollGestureAndroid() {
-}
-
-bool TouchSmoothScrollGestureAndroid::ForwardInputEvents(
- base::TimeTicks now, RenderWidgetHost* host) {
- if (!has_started_) {
- has_started_ = true;
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_SmoothScroller_start(
- env, java_scroller_.obj(), reinterpret_cast<int>(this));
- }
-
- TRACE_COUNTER_ID1(
- "gpu", "smooth_scroll_by_pixels_scrolled", this, pixels_scrolled_);
-
- return !has_sent_motion_up_;
-}
-
-double TouchSmoothScrollGestureAndroid::GetScrollDelta(
- JNIEnv* env, jobject obj, double scale) {
- double delta = smooth_scroll_calculator_.GetScrollDelta(
- base::TimeTicks::Now(),
- RenderWidgetHostImpl::From(rwh_)->GetSyntheticScrollMessageInterval())
- * scale;
- pixels_scrolled_ += delta;
- return delta;
-}
-
-bool TouchSmoothScrollGestureAndroid::HasFinished(JNIEnv* env, jobject obj) {
- return pixels_scrolled_ >= pixels_to_scroll_;
-}
-
-void TouchSmoothScrollGestureAndroid::SetHasSentMotionUp(
- JNIEnv* env, jobject obj) {
- has_sent_motion_up_ = true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h
deleted file mode 100644
index 0b892670643..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_android.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_GESTURE_ANDROID_H_
-#define CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_GESTURE_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
-
-namespace content {
-
-class ContentViewCore;
-class RenderWidgetHost;
-
-class TouchSmoothScrollGestureAndroid : public SmoothScrollGesture {
- public:
- TouchSmoothScrollGestureAndroid(
- int pixels_to_scroll,
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_scroller);
-
- // Called by the java side once the TimeAnimator ticks.
- double GetScrollDelta(JNIEnv* env, jobject obj, double scale);
- bool HasFinished(JNIEnv* env, jobject obj);
- void SetHasSentMotionUp(JNIEnv* env, jobject obj);
-
- // SmoothScrollGesture
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE;
-
- private:
- virtual ~TouchSmoothScrollGestureAndroid();
-
- SmoothScrollCalculator smooth_scroll_calculator_;
-
- int pixels_scrolled_;
- bool has_started_;
- bool has_sent_motion_up_;
-
- int pixels_to_scroll_;
- RenderWidgetHost* rwh_;
- base::android::ScopedJavaGlobalRef<jobject> java_scroller_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchSmoothScrollGestureAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_GESTURE_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
index ffb1564ded1..5df932dfa3b 100644
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
+++ b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
@@ -6,8 +6,8 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "ui/aura/root_window.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/transform.h"
namespace {
@@ -53,8 +53,8 @@ bool TouchSmoothScrollGestureAura::ForwardInputEvents(
return false;
RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(host);
- double position_delta = smooth_scroll_calculator_.GetScrollDelta(now,
- host_impl->GetSyntheticScrollMessageInterval());
+ float position_delta = synthetic_gesture_calculator_.GetDelta(now,
+ host_impl->GetSyntheticGestureMessageInterval());
if (pixels_scrolled_ == 0) {
InjectTouchEvent(location_, ui::ET_TOUCH_PRESSED, window_);
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
index 779e02d6dd0..890b1467d68 100644
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
+++ b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
@@ -6,8 +6,8 @@
#define CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_SCROLL_GESTURE_
#include "base/time/time.h"
-#include "content/browser/renderer_host/smooth_scroll_calculator.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
+#include "content/port/browser/synthetic_gesture.h"
#include "ui/gfx/point.h"
namespace aura {
@@ -16,7 +16,7 @@ class Window;
namespace content {
-class TouchSmoothScrollGestureAura : public SmoothScrollGesture {
+class TouchSmoothScrollGestureAura : public SyntheticGesture {
public:
TouchSmoothScrollGestureAura(bool scroll_down,
int pixels_to_scroll,
@@ -35,7 +35,7 @@ class TouchSmoothScrollGestureAura : public SmoothScrollGesture {
int pixels_scrolled_;
gfx::Point location_;
aura::Window* window_;
- SmoothScrollCalculator smooth_scroll_calculator_;
+ SyntheticGestureCalculator synthetic_gesture_calculator_;
DISALLOW_COPY_AND_ASSIGN(TouchSmoothScrollGestureAura);
};
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 89242946cab..78a7bff4f74 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -5,8 +5,8 @@
#include "content/browser/renderer_host/ui_events_helper.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_constants.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
namespace {
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.cc b/chromium/content/browser/renderer_host/web_input_event_aura.cc
index 8931f1f5d91..6bb5e5838af 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -6,11 +6,57 @@
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/window.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
namespace content {
+#if defined(USE_X11) || defined(USE_OZONE)
+// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
+WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
+ if (windows_key_code >= ui::VKEY_A &&
+ windows_key_code <= ui::VKEY_Z) {
+ // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
+ return windows_key_code - ui::VKEY_A + 1;
+ }
+ if (shift) {
+ // following graphics chars require shift key to input.
+ switch (windows_key_code) {
+ // ctrl-@ maps to \x00 (Null byte)
+ case ui::VKEY_2:
+ return 0;
+ // ctrl-^ maps to \x1E (Record separator, Information separator two)
+ case ui::VKEY_6:
+ return 0x1E;
+ // ctrl-_ maps to \x1F (Unit separator, Information separator one)
+ case ui::VKEY_OEM_MINUS:
+ return 0x1F;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ break;
+ }
+ } else {
+ switch (windows_key_code) {
+ // ctrl-[ maps to \x1B (Escape)
+ case ui::VKEY_OEM_4:
+ return 0x1B;
+ // ctrl-\ maps to \x1C (File separator, Information separator four)
+ case ui::VKEY_OEM_5:
+ return 0x1C;
+ // ctrl-] maps to \x1D (Group separator, Information separator three)
+ case ui::VKEY_OEM_6:
+ return 0x1D;
+ // ctrl-Enter maps to \x0A (Line feed)
+ case ui::VKEY_RETURN:
+ return 0x0A;
+ // Returns 0 for all other keys to avoid inputting unexpected chars.
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+#endif
#if defined(OS_WIN)
WebKit::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
base::NativeEvent native_event);
@@ -21,28 +67,104 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
WebKit::WebGestureEvent MakeWebGestureEventFromNativeEvent(
base::NativeEvent native_event);
#elif defined(USE_X11)
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
- ui::ScrollEvent* event);
WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event);
-WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
- ui::ScrollEvent* event);
-#else
+#elif defined(USE_OZONE)
+WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+ ui::KeyEvent* event) {
+ base::NativeEvent native_event = event->native_event();
+ ui::EventType type = ui::EventTypeFromNative(native_event);
+ WebKit::WebKeyboardEvent webkit_event;
+
+ webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
+ webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
+
+ switch (type) {
+ case ui::ET_KEY_PRESSED:
+ webkit_event.type = event->is_char() ? WebKit::WebInputEvent::Char :
+ WebKit::WebInputEvent::RawKeyDown;
+ break;
+ case ui::ET_KEY_RELEASED:
+ webkit_event.type = WebKit::WebInputEvent::KeyUp;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ if (webkit_event.modifiers & WebKit::WebInputEvent::AltKey)
+ webkit_event.isSystemKey = true;
+
+ wchar_t character = ui::KeyboardCodeFromNative(native_event);
+ webkit_event.windowsKeyCode = character;
+ webkit_event.nativeKeyCode = character;
+
+ if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
+ webkit_event.unmodifiedText[0] = '\r';
+ else
+ webkit_event.unmodifiedText[0] = character;
+
+ if (webkit_event.modifiers & WebKit::WebInputEvent::ControlKey) {
+ webkit_event.text[0] =
+ GetControlCharacter(
+ webkit_event.windowsKeyCode,
+ webkit_event.modifiers & WebKit::WebInputEvent::ShiftKey);
+ } else {
+ webkit_event.text[0] = webkit_event.unmodifiedText[0];
+ }
+
+ webkit_event.setKeyIdentifierFromWindowsKeyCode();
+
+ return webkit_event;
+}
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::ScrollEvent* event) {
WebKit::WebMouseWheelEvent webkit_event;
- return webkit_event;
-}
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
- ui::KeyEvent* event) {
- WebKit::WebKeyboardEvent webkit_event;
+ webkit_event.type = WebKit::WebInputEvent::MouseWheel;
+ webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
+ webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
+ webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
+ webkit_event.hasPreciseScrollingDeltas = true;
+ webkit_event.deltaX = event->x_offset();
+ if (event->x_offset_ordinal() != 0.f && event->x_offset() != 0.f) {
+ webkit_event.accelerationRatioX =
+ event->x_offset_ordinal() / event->x_offset();
+ }
+ webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
+ webkit_event.deltaY = event->y_offset();
+ webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
+ if (event->y_offset_ordinal() != 0.f && event->y_offset() != 0.f) {
+ webkit_event.accelerationRatioY =
+ event->y_offset_ordinal() / event->y_offset();
+ }
return webkit_event;
}
WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
ui::ScrollEvent* event) {
WebKit::WebGestureEvent webkit_event;
+
+ switch (event->type()) {
+ case ui::ET_SCROLL_FLING_START:
+ webkit_event.type = WebKit::WebInputEvent::GestureFlingStart;
+ webkit_event.data.flingStart.velocityX = event->x_offset();
+ webkit_event.data.flingStart.velocityY = event->y_offset();
+ break;
+ case ui::ET_SCROLL_FLING_CANCEL:
+ webkit_event.type = WebKit::WebInputEvent::GestureFlingCancel;
+ break;
+ case ui::ET_SCROLL:
+ NOTREACHED() << "Invalid gesture type: " << event->type();
+ break;
+ default:
+ NOTREACHED() << "Unknown gesture type: " << event->type();
+ }
+
+ webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
+ webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
+ webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
return webkit_event;
}
@@ -234,6 +356,7 @@ WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
break;
case ui::ET_MOUSE_RELEASED:
webkit_event.type = WebKit::WebInputEvent::MouseUp;
+ webkit_event.clickCount = event->GetClickCount();
break;
case ui::ET_MOUSE_ENTERED:
case ui::ET_MOUSE_EXITED:
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.h b/chromium/content/browser/renderer_host/web_input_event_aura.h
index ddc59e0c46f..3c4c8945bed 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.h
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.h
@@ -22,6 +22,10 @@ namespace content {
// Used for scrolling. This matches Firefox behavior.
const int kPixelsPerTick = 53;
+#if defined(USE_X11) || defined(USE_OZONE)
+CONTENT_EXPORT WebKit::WebUChar GetControlCharacter(
+ int windows_key_code, bool shift);
+#endif
CONTENT_EXPORT WebKit::WebMouseEvent MakeWebMouseEvent(
ui::MouseEvent* event);
CONTENT_EXPORT WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
index 0443c30dad9..818250c0dd6 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
@@ -6,11 +6,12 @@
#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/events/event.h"
+#include "ui/events/event.h"
#if defined(USE_X11)
#include <X11/keysym.h>
#include <X11/Xlib.h>
+#include "ui/gfx/x/x11_types.h"
#include "ui/base/x/x11_util.h"
#endif
@@ -56,7 +57,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
ui::VKEY_CONTROL,
0, // X does not set ControlMask for KeyPress.
&xev);
- xev.xkey.keycode = XKeysymToKeycode(ui::GetXDisplay(), XK_Control_L);
+ xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
ui::KeyEvent event(&xev, false /* is_char */);
WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_LCONTROL, instead of ui::VKEY_CONTROL, should be filled.
@@ -68,7 +69,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
ui::VKEY_CONTROL,
0, // X does not set ControlMask for KeyPress.
&xev);
- xev.xkey.keycode = XKeysymToKeycode(ui::GetXDisplay(), XK_Control_R);
+ xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_R);
ui::KeyEvent event(&xev, false /* is_char */);
WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_RCONTROL, instead of ui::VKEY_CONTROL, should be filled.
diff --git a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
index fdde17edc7b..76ae55f5f19 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
@@ -45,10 +45,10 @@
#include "base/event_types.h"
#include "base/logging.h"
#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/base/events/event.h"
-#include "ui/base/events/event_constants.h"
-#include "ui/base/keycodes/keyboard_code_conversion_x.h"
-#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
@@ -87,106 +87,8 @@ int XKeyEventToWindowsKeyCode(XKeyEvent* event) {
return windows_key_code;
}
-// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
-WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
- if (windows_key_code >= ui::VKEY_A &&
- windows_key_code <= ui::VKEY_Z) {
- // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
- return windows_key_code - ui::VKEY_A + 1;
- }
- if (shift) {
- // following graphics chars require shift key to input.
- switch (windows_key_code) {
- // ctrl-@ maps to \x00 (Null byte)
- case ui::VKEY_2:
- return 0;
- // ctrl-^ maps to \x1E (Record separator, Information separator two)
- case ui::VKEY_6:
- return 0x1E;
- // ctrl-_ maps to \x1F (Unit separator, Information separator one)
- case ui::VKEY_OEM_MINUS:
- return 0x1F;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- } else {
- switch (windows_key_code) {
- // ctrl-[ maps to \x1B (Escape)
- case ui::VKEY_OEM_4:
- return 0x1B;
- // ctrl-\ maps to \x1C (File separator, Information separator four)
- case ui::VKEY_OEM_5:
- return 0x1C;
- // ctrl-] maps to \x1D (Group separator, Information separator three)
- case ui::VKEY_OEM_6:
- return 0x1D;
- // ctrl-Enter maps to \x0A (Line feed)
- case ui::VKEY_RETURN:
- return 0x0A;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- }
- return 0;
-}
-
} // namespace
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
- ui::ScrollEvent* event) {
- WebKit::WebMouseWheelEvent webkit_event;
-
- webkit_event.type = WebKit::WebInputEvent::MouseWheel;
- webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
- webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
- webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
- webkit_event.hasPreciseScrollingDeltas = true;
- webkit_event.deltaX = event->x_offset();
- if (event->x_offset_ordinal() != 0.f && event->x_offset() != 0.f) {
- webkit_event.accelerationRatioX =
- event->x_offset_ordinal() / event->x_offset();
- }
- webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
- webkit_event.deltaY = event->y_offset();
- webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
- if (event->y_offset_ordinal() != 0.f && event->y_offset() != 0.f) {
- webkit_event.accelerationRatioY =
- event->y_offset_ordinal() / event->y_offset();
- }
-
- return webkit_event;
-}
-
-// NOTE: ui::ScrollEvent instances come from the touchpad.
-WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
- ui::ScrollEvent* event) {
- WebKit::WebGestureEvent webkit_event;
-
- switch (event->type()) {
- case ui::ET_SCROLL_FLING_START:
- webkit_event.type = WebKit::WebInputEvent::GestureFlingStart;
- webkit_event.data.flingStart.velocityX = event->x_offset();
- webkit_event.data.flingStart.velocityY = event->y_offset();
- break;
- case ui::ET_SCROLL_FLING_CANCEL:
- webkit_event.type = WebKit::WebInputEvent::GestureFlingCancel;
- break;
- case ui::ET_SCROLL:
- NOTREACHED() << "Invalid gesture type: " << event->type();
- break;
- default:
- NOTREACHED() << "Unknown gesture type: " << event->type();
- }
-
- webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
- webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
- webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
-
- return webkit_event;
-}
-
WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event) {
base::NativeEvent native_event = event->native_event();