Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_guest.cc
blob70168b41c4335575a2cadb4abf071627b3138d77
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind_helpers.h"
6 #include "base/command_line.h"
7 #include "base/logging.h"
8 #include "base/message_loop.h"
9 #include "content/browser/browser_plugin/browser_plugin_guest.h"
10 #include "content/browser/renderer_host/render_view_host_impl.h"
11 #include "content/browser/renderer_host/render_widget_host_view_guest.h"
12 #if defined(OS_WIN) || defined(USE_AURA)
13 #include "content/browser/renderer_host/ui_events_helper.h"
14 #endif
15 #include "content/common/browser_plugin/browser_plugin_messages.h"
16 #include "content/common/gpu/gpu_messages.h"
17 #include "content/common/view_messages.h"
18 #include "content/public/common/content_switches.h"
19 #include "skia/ext/platform_canvas.h"
20 #include "third_party/WebKit/public/web/WebScreenInfo.h"
21 #include "webkit/plugins/npapi/webplugin.h"
23 namespace content {
25 namespace {
27 bool ShouldSendPinchGesture() {
28 static bool pinch_allowed =
29 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
30 return pinch_allowed;
33 WebKit::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
34 WebKit::WebGestureEvent gesture_event;
35 gesture_event.timeStampSeconds = time_stamp;
36 gesture_event.type = WebKit::WebGestureEvent::GestureFlingCancel;
37 gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
38 return gesture_event;
41 } // namespace
43 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
44 RenderWidgetHost* widget_host,
45 BrowserPluginGuest* guest,
46 RenderWidgetHostView* platform_view)
47 : host_(RenderWidgetHostImpl::From(widget_host)),
48 guest_(guest),
49 is_hidden_(false),
50 platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) {
51 #if defined(OS_WIN) || defined(USE_AURA)
52 gesture_recognizer_.reset(ui::GestureRecognizer::Create(this));
53 #endif // defined(OS_WIN) || defined(USE_AURA)
54 host_->SetView(this);
57 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
60 RenderWidgetHost* RenderWidgetHostViewGuest::GetRenderWidgetHost() const {
61 return host_;
64 void RenderWidgetHostViewGuest::WasShown() {
65 if (!is_hidden_)
66 return;
67 is_hidden_ = false;
68 host_->WasShown();
71 void RenderWidgetHostViewGuest::WasHidden() {
72 if (is_hidden_)
73 return;
74 is_hidden_ = true;
75 host_->WasHidden();
78 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
79 size_ = size;
80 host_->WasResized();
83 gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
84 // We do not have any root window specific parts in this view.
85 return GetViewBounds();
88 gfx::GLSurfaceHandle RenderWidgetHostViewGuest::GetCompositingSurface() {
89 return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
92 #if defined(OS_WIN) || defined(USE_AURA)
93 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
94 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
95 // TODO(fsamuel): Currently we will only take this codepath if the guest has
96 // requested touch events. A better solution is to always forward touchpresses
97 // to the embedder process to target a BrowserPlugin, and then route all
98 // subsequent touch points of that touchdown to the appropriate guest until
99 // that touch point is released.
100 ScopedVector<ui::TouchEvent> events;
101 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
102 return;
104 ui::EventResult result = (ack_result ==
105 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
106 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
107 end = events.end(); iter != end; ++iter) {
108 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
109 gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
110 *(*iter), result, this));
111 ProcessGestures(gestures.get());
114 #endif
116 void RenderWidgetHostViewGuest::Show() {
117 WasShown();
120 void RenderWidgetHostViewGuest::Hide() {
121 WasHidden();
124 bool RenderWidgetHostViewGuest::IsShowing() {
125 return !is_hidden_;
128 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
129 gfx::Rect embedder_bounds = static_cast<RenderWidgetHostViewPort*>(
130 guest_->GetEmbedderRenderWidgetHostView())->GetViewBounds();
131 gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
132 shifted_rect.set_width(size_.width());
133 shifted_rect.set_height(size_.height());
134 return shifted_rect;
137 void RenderWidgetHostViewGuest::RenderViewGone(base::TerminationStatus status,
138 int error_code) {
139 platform_view_->RenderViewGone(status, error_code);
140 // Destroy the guest view instance only, so we don't end up calling
141 // platform_view_->Destroy().
142 DestroyGuestView();
145 void RenderWidgetHostViewGuest::Destroy() {
146 platform_view_->Destroy();
147 // The RenderWidgetHost's destruction led here, so don't call it.
148 DestroyGuestView();
151 void RenderWidgetHostViewGuest::SetTooltipText(const string16& tooltip_text) {
152 platform_view_->SetTooltipText(tooltip_text);
155 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
156 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
157 int gpu_host_id) {
158 // If accelerated surface buffers are getting swapped then we're not using
159 // the software path.
160 guest_->clear_damage_buffer();
161 guest_->SendMessageToEmbedder(
162 new BrowserPluginMsg_BuffersSwapped(
163 guest_->instance_id(),
164 params.size,
165 params.mailbox_name,
166 params.route_id,
167 gpu_host_id));
170 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
171 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
172 int gpu_host_id) {
173 NOTREACHED();
176 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
177 scoped_ptr<cc::CompositorFrame> frame) {
178 if (frame->software_frame_data) {
179 cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
180 #ifdef OS_WIN
181 base::SharedMemory shared_memory(frame_data->handle, true,
182 host_->GetProcess()->GetHandle());
183 #else
184 base::SharedMemory shared_memory(frame_data->handle, true);
185 #endif
187 RenderWidgetHostView* embedder_view =
188 guest_->GetEmbedderRenderWidgetHostView();
189 base::ProcessHandle embedder_pid =
190 embedder_view->GetRenderWidgetHost()->GetProcess()->GetHandle();
192 shared_memory.GiveToProcess(embedder_pid, &frame_data->handle);
195 guest_->clear_damage_buffer();
196 guest_->SendMessageToEmbedder(
197 new BrowserPluginMsg_CompositorFrameSwapped(
198 guest_->instance_id(),
199 *frame,
200 host_->GetRoutingID(),
201 host_->GetProcess()->GetID()));
204 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
205 SetSize(rect.size());
208 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
209 return platform_view_->OnMessageReceived(msg);
212 void RenderWidgetHostViewGuest::InitAsChild(
213 gfx::NativeView parent_view) {
214 platform_view_->InitAsChild(parent_view);
217 void RenderWidgetHostViewGuest::InitAsPopup(
218 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
219 // This should never get called.
220 NOTREACHED();
223 void RenderWidgetHostViewGuest::InitAsFullscreen(
224 RenderWidgetHostView* reference_host_view) {
225 // This should never get called.
226 NOTREACHED();
229 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
230 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeView();
233 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
234 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewId();
237 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
238 return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewAccessible();
241 void RenderWidgetHostViewGuest::MovePluginWindows(
242 const gfx::Vector2d& scroll_offset,
243 const std::vector<webkit::npapi::WebPluginGeometry>& moves) {
244 platform_view_->MovePluginWindows(scroll_offset, moves);
247 void RenderWidgetHostViewGuest::Focus() {
250 void RenderWidgetHostViewGuest::Blur() {
253 bool RenderWidgetHostViewGuest::HasFocus() const {
254 return false;
257 bool RenderWidgetHostViewGuest::IsSurfaceAvailableForCopy() const {
258 NOTIMPLEMENTED();
259 return false;
262 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
263 platform_view_->UpdateCursor(cursor);
266 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
267 platform_view_->SetIsLoading(is_loading);
270 void RenderWidgetHostViewGuest::TextInputTypeChanged(ui::TextInputType type,
271 bool can_compose_inline) {
272 RenderWidgetHostViewPort::FromRWHV(
273 guest_->GetEmbedderRenderWidgetHostView())->
274 TextInputTypeChanged(type, can_compose_inline);
277 void RenderWidgetHostViewGuest::ImeCancelComposition() {
278 platform_view_->ImeCancelComposition();
281 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
282 const ui::Range& range,
283 const std::vector<gfx::Rect>& character_bounds) {
286 void RenderWidgetHostViewGuest::DidUpdateBackingStore(
287 const gfx::Rect& scroll_rect,
288 const gfx::Vector2d& scroll_delta,
289 const std::vector<gfx::Rect>& copy_rects,
290 const ui::LatencyInfo& latency_info) {
291 NOTREACHED();
294 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
295 const ViewHostMsg_SelectionBounds_Params& params) {
296 platform_view_->SelectionBoundsChanged(params);
299 void RenderWidgetHostViewGuest::ScrollOffsetChanged() {
302 BackingStore* RenderWidgetHostViewGuest::AllocBackingStore(
303 const gfx::Size& size) {
304 NOTREACHED();
305 return NULL;
308 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
309 const gfx::Rect& src_subrect,
310 const gfx::Size& /* dst_size */,
311 const base::Callback<void(bool, const SkBitmap&)>& callback) {
312 callback.Run(false, SkBitmap());
315 void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame(
316 const gfx::Rect& src_subrect,
317 const scoped_refptr<media::VideoFrame>& target,
318 const base::Callback<void(bool)>& callback) {
319 NOTIMPLEMENTED();
320 callback.Run(false);
323 bool RenderWidgetHostViewGuest::CanCopyToVideoFrame() const {
324 return false;
327 void RenderWidgetHostViewGuest::AcceleratedSurfaceSuspend() {
328 NOTREACHED();
331 void RenderWidgetHostViewGuest::AcceleratedSurfaceRelease() {
334 bool RenderWidgetHostViewGuest::HasAcceleratedSurface(
335 const gfx::Size& desired_size) {
336 return false;
339 void RenderWidgetHostViewGuest::SetBackground(const SkBitmap& background) {
340 platform_view_->SetBackground(background);
343 #if defined(OS_WIN) && !defined(USE_AURA)
344 void RenderWidgetHostViewGuest::SetClickthroughRegion(SkRegion* region) {
346 #endif
348 #if defined(OS_WIN) && defined(USE_AURA)
349 gfx::NativeViewAccessible
350 RenderWidgetHostViewGuest::AccessibleObjectFromChildId(long child_id) {
351 NOTIMPLEMENTED();
352 return NULL;
354 #endif
356 void RenderWidgetHostViewGuest::SetHasHorizontalScrollbar(
357 bool has_horizontal_scrollbar) {
358 platform_view_->SetHasHorizontalScrollbar(has_horizontal_scrollbar);
361 void RenderWidgetHostViewGuest::SetScrollOffsetPinning(
362 bool is_pinned_to_left, bool is_pinned_to_right) {
363 platform_view_->SetScrollOffsetPinning(
364 is_pinned_to_left, is_pinned_to_right);
367 void RenderWidgetHostViewGuest::OnAcceleratedCompositingStateChange() {
370 bool RenderWidgetHostViewGuest::LockMouse() {
371 return platform_view_->LockMouse();
374 void RenderWidgetHostViewGuest::UnlockMouse() {
375 return platform_view_->UnlockMouse();
378 void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
379 RenderWidgetHostViewPort* embedder_view =
380 RenderWidgetHostViewPort::FromRWHV(
381 guest_->GetEmbedderRenderWidgetHostView());
382 embedder_view->GetScreenInfo(results);
385 void RenderWidgetHostViewGuest::OnAccessibilityNotifications(
386 const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
389 #if defined(OS_MACOSX)
390 void RenderWidgetHostViewGuest::SetActive(bool active) {
391 platform_view_->SetActive(active);
394 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
395 platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
398 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
399 platform_view_->SetWindowVisibility(visible);
402 void RenderWidgetHostViewGuest::WindowFrameChanged() {
403 platform_view_->WindowFrameChanged();
406 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
407 platform_view_->ShowDefinitionForSelection();
410 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
411 return platform_view_->SupportsSpeech();
414 void RenderWidgetHostViewGuest::SpeakSelection() {
415 platform_view_->SpeakSelection();
418 bool RenderWidgetHostViewGuest::IsSpeaking() const {
419 return platform_view_->IsSpeaking();
422 void RenderWidgetHostViewGuest::StopSpeaking() {
423 platform_view_->StopSpeaking();
426 void RenderWidgetHostViewGuest::AboutToWaitForBackingStoreMsg() {
427 NOTREACHED();
430 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
431 const NativeWebKeyboardEvent& event) {
432 return false;
435 #endif // defined(OS_MACOSX)
437 #if defined(OS_ANDROID)
438 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
439 const gfx::Rect& target_rect,
440 const SkBitmap& zoomed_bitmap) {
443 void RenderWidgetHostViewGuest::HasTouchEventHandlers(bool need_touch_events) {
445 #endif // defined(OS_ANDROID)
447 #if defined(TOOLKIT_GTK)
448 GdkEventButton* RenderWidgetHostViewGuest::GetLastMouseDown() {
449 return NULL;
452 gfx::NativeView RenderWidgetHostViewGuest::BuildInputMethodsGtkMenu() {
453 return platform_view_->BuildInputMethodsGtkMenu();
455 #endif // defined(TOOLKIT_GTK)
457 #if defined(OS_WIN) && !defined(USE_AURA)
458 void RenderWidgetHostViewGuest::WillWmDestroy() {
460 #endif
462 #if defined(OS_WIN) && defined(USE_AURA)
463 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
464 gfx::NativeViewAccessible accessible_parent) {
466 #endif
468 void RenderWidgetHostViewGuest::DestroyGuestView() {
469 host_ = NULL;
470 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
473 bool RenderWidgetHostViewGuest::DispatchLongPressGestureEvent(
474 ui::GestureEvent* event) {
475 return ForwardGestureEventToRenderer(event);
478 bool RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
479 ui::TouchEvent* event) {
480 if (!host_)
481 return false;
483 WebKit::WebTouchEvent cancel_event;
484 cancel_event.type = WebKit::WebInputEvent::TouchCancel;
485 cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
486 host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
487 return true;
490 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
491 ui::GestureEvent* gesture) {
492 #if defined(OS_WIN) || defined(USE_AURA)
493 if (!host_)
494 return false;
496 // Pinch gestures are disabled by default on windows desktop. See
497 // crbug.com/128477 and crbug.com/148816
498 if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
499 gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
500 gesture->type() == ui::ET_GESTURE_PINCH_END) &&
501 !ShouldSendPinchGesture()) {
502 return true;
505 WebKit::WebGestureEvent web_gesture =
506 MakeWebGestureEventFromUIEvent(*gesture);
507 const gfx::Point& client_point = gesture->location();
508 const gfx::Point& screen_point = gesture->location();
510 web_gesture.x = client_point.x();
511 web_gesture.y = client_point.y();
512 web_gesture.globalX = screen_point.x();
513 web_gesture.globalY = screen_point.y();
515 if (web_gesture.type == WebKit::WebGestureEvent::Undefined)
516 return false;
517 if (web_gesture.type == WebKit::WebGestureEvent::GestureTapDown) {
518 host_->ForwardGestureEvent(
519 CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
521 host_->ForwardGestureEvent(web_gesture);
522 return true;
523 #else
524 return false;
525 #endif
528 void RenderWidgetHostViewGuest::ProcessGestures(
529 ui::GestureRecognizer::Gestures* gestures) {
530 if ((gestures == NULL) || gestures->empty())
531 return;
532 for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
533 g_it != gestures->end();
534 ++g_it) {
535 ForwardGestureEventToRenderer(*g_it);
540 } // namespace content