Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_view_win.cc
blob0c65b1dc181f4d1ab98c7b5d138a2ef2f244f9a1
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 "content/browser/web_contents/web_contents_view_win.h"
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "content/browser/renderer_host/render_view_host_factory.h"
10 #include "content/browser/renderer_host/render_view_host_impl.h"
11 #include "content/browser/renderer_host/render_widget_host_view_win.h"
12 #include "content/browser/web_contents/interstitial_page_impl.h"
13 #include "content/browser/web_contents/web_contents_drag_win.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/browser/web_contents/web_drag_dest_win.h"
16 #include "content/public/browser/web_contents_delegate.h"
17 #include "content/public/browser/web_contents_view_delegate.h"
18 #include "ui/base/win/hidden_window.h"
19 #include "ui/base/win/hwnd_subclass.h"
20 #include "ui/gfx/screen.h"
22 namespace content {
23 WebContentsViewPort* CreateWebContentsView(
24 WebContentsImpl* web_contents,
25 WebContentsViewDelegate* delegate,
26 RenderViewHostDelegateView** render_view_host_delegate_view) {
27 WebContentsViewWin* rv = new WebContentsViewWin(web_contents, delegate);
28 *render_view_host_delegate_view = rv;
29 return rv;
32 namespace {
34 typedef std::map<HWND, WebContentsViewWin*> HwndToWcvMap;
35 HwndToWcvMap hwnd_to_wcv_map;
37 void RemoveHwndToWcvMapEntry(WebContentsViewWin* wcv) {
38 HwndToWcvMap::iterator it;
39 for (it = hwnd_to_wcv_map.begin(); it != hwnd_to_wcv_map.end();) {
40 if (it->second == wcv)
41 hwnd_to_wcv_map.erase(it++);
42 else
43 ++it;
47 BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
48 HwndToWcvMap::iterator it = hwnd_to_wcv_map.find(hwnd);
49 if (it == hwnd_to_wcv_map.end())
50 return TRUE; // must return TRUE to continue enumeration.
51 WebContentsViewWin* wcv = it->second;
52 RenderWidgetHostViewWin* rwhv = static_cast<RenderWidgetHostViewWin*>(
53 wcv->web_contents()->GetRenderWidgetHostView());
54 if (rwhv)
55 rwhv->UpdateScreenInfo(rwhv->GetNativeView());
57 return TRUE; // must return TRUE to continue enumeration.
60 class PositionChangedMessageFilter : public ui::HWNDMessageFilter {
61 public:
62 PositionChangedMessageFilter() {}
64 private:
65 // Overridden from ui::HWNDMessageFilter:
66 virtual bool FilterMessage(HWND hwnd,
67 UINT message,
68 WPARAM w_param,
69 LPARAM l_param,
70 LRESULT* l_result) OVERRIDE {
71 if (message == WM_WINDOWPOSCHANGED || message == WM_SETTINGCHANGE)
72 EnumChildWindows(hwnd, EnumChildProc, 0);
74 return false;
77 DISALLOW_COPY_AND_ASSIGN(PositionChangedMessageFilter);
80 void AddFilterToParentHwndSubclass(HWND hwnd, ui::HWNDMessageFilter* filter) {
81 HWND parent = ::GetAncestor(hwnd, GA_ROOT);
82 if (parent) {
83 ui::HWNDSubclass::RemoveFilterFromAllTargets(filter);
84 ui::HWNDSubclass::AddFilterToTarget(parent, filter);
88 } // namespace namespace
90 WebContentsViewWin::WebContentsViewWin(WebContentsImpl* web_contents,
91 WebContentsViewDelegate* delegate)
92 : web_contents_(web_contents),
93 delegate_(delegate),
94 hwnd_message_filter_(new PositionChangedMessageFilter) {
97 WebContentsViewWin::~WebContentsViewWin() {
98 RemoveHwndToWcvMapEntry(this);
100 if (IsWindow(hwnd()))
101 DestroyWindow(hwnd());
104 gfx::NativeView WebContentsViewWin::GetNativeView() const {
105 return hwnd();
108 gfx::NativeView WebContentsViewWin::GetContentNativeView() const {
109 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
110 return rwhv ? rwhv->GetNativeView() : NULL;
113 gfx::NativeWindow WebContentsViewWin::GetTopLevelNativeWindow() const {
114 return ::GetAncestor(GetNativeView(), GA_ROOT);
117 void WebContentsViewWin::GetContainerBounds(gfx::Rect *out) const {
118 // Copied from NativeWidgetWin::GetClientAreaScreenBounds().
119 RECT r;
120 GetClientRect(hwnd(), &r);
121 POINT point = { r.left, r.top };
122 ClientToScreen(hwnd(), &point);
123 *out = gfx::Rect(point.x, point.y, r.right - r.left, r.bottom - r.top);
126 void WebContentsViewWin::OnTabCrashed(base::TerminationStatus status,
127 int error_code) {
130 void WebContentsViewWin::SizeContents(const gfx::Size& size) {
131 gfx::Rect bounds;
132 GetContainerBounds(&bounds);
133 if (bounds.size() != size) {
134 SetWindowPos(hwnd(), NULL, 0, 0, size.width(), size.height(),
135 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
136 } else {
137 // Our size matches what we want but the renderers size may not match.
138 // Pretend we were resized so that the renderers size is updated too.
139 if (web_contents_->GetInterstitialPage())
140 web_contents_->GetInterstitialPage()->SetSize(size);
141 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
142 if (rwhv)
143 rwhv->SetSize(size);
147 void WebContentsViewWin::CreateView(
148 const gfx::Size& initial_size, gfx::NativeView context) {
149 initial_size_ = initial_size;
151 set_window_style(WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
153 Init(ui::GetHiddenWindow(), gfx::Rect(initial_size_));
155 // Remove the root view drop target so we can register our own.
156 RevokeDragDrop(GetNativeView());
157 drag_dest_ = new WebDragDest(hwnd(), web_contents_);
158 if (delegate_) {
159 WebDragDestDelegate* delegate = delegate_->GetDragDestDelegate();
160 if (delegate)
161 drag_dest_->set_delegate(delegate);
165 void WebContentsViewWin::Focus() {
166 if (web_contents_->GetInterstitialPage()) {
167 web_contents_->GetInterstitialPage()->Focus();
168 return;
171 if (delegate_.get() && delegate_->Focus())
172 return;
174 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
175 if (rwhv)
176 rwhv->Focus();
179 void WebContentsViewWin::SetInitialFocus() {
180 if (web_contents_->FocusLocationBarByDefault())
181 web_contents_->SetFocusToLocationBar(false);
182 else
183 Focus();
186 void WebContentsViewWin::StoreFocus() {
187 if (delegate_)
188 delegate_->StoreFocus();
191 void WebContentsViewWin::RestoreFocus() {
192 if (delegate_)
193 delegate_->RestoreFocus();
196 DropData* WebContentsViewWin::GetDropData() const {
197 return drag_dest_->current_drop_data();
200 gfx::Rect WebContentsViewWin::GetViewBounds() const {
201 RECT r;
202 GetWindowRect(hwnd(), &r);
203 return gfx::Rect(r);
206 RenderWidgetHostView* WebContentsViewWin::CreateViewForWidget(
207 RenderWidgetHost* render_widget_host) {
208 if (render_widget_host->GetView()) {
209 // During testing, the view will already be set up in most cases to the
210 // test view, so we don't want to clobber it with a real one. To verify that
211 // this actually is happening (and somebody isn't accidentally creating the
212 // view twice), we check for the RVH Factory, which will be set when we're
213 // making special ones (which go along with the special views).
214 DCHECK(RenderViewHostFactory::has_factory());
215 return render_widget_host->GetView();
218 RenderWidgetHostViewWin* view = static_cast<RenderWidgetHostViewWin*>(
219 RenderWidgetHostView::CreateViewForWidget(render_widget_host));
220 view->CreateWnd(GetNativeView());
221 view->ShowWindow(SW_SHOW);
222 view->SetSize(initial_size_);
223 return view;
226 RenderWidgetHostView* WebContentsViewWin::CreateViewForPopupWidget(
227 RenderWidgetHost* render_widget_host) {
228 return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
231 void WebContentsViewWin::SetPageTitle(const string16& title) {
232 // It's possible to get this after the hwnd has been destroyed.
233 if (GetNativeView())
234 ::SetWindowText(GetNativeView(), title.c_str());
237 void WebContentsViewWin::RenderViewCreated(RenderViewHost* host) {
240 void WebContentsViewWin::RenderViewSwappedIn(RenderViewHost* host) {
243 void WebContentsViewWin::SetOverscrollControllerEnabled(bool enabled) {
246 void WebContentsViewWin::ShowContextMenu(const ContextMenuParams& params) {
247 if (delegate_)
248 delegate_->ShowContextMenu(params);
249 // WARNING: this may have been deleted.
252 void WebContentsViewWin::ShowPopupMenu(const gfx::Rect& bounds,
253 int item_height,
254 double item_font_size,
255 int selected_item,
256 const std::vector<MenuItem>& items,
257 bool right_aligned,
258 bool allow_multiple_selection) {
259 // External popup menus are only used on Mac and Android.
260 NOTIMPLEMENTED();
263 void WebContentsViewWin::StartDragging(const DropData& drop_data,
264 WebKit::WebDragOperationsMask operations,
265 const gfx::ImageSkia& image,
266 const gfx::Vector2d& image_offset,
267 const DragEventSourceInfo& event_info) {
268 drag_handler_ = new WebContentsDragWin(
269 GetNativeView(),
270 web_contents_,
271 drag_dest_,
272 base::Bind(&WebContentsViewWin::EndDragging, base::Unretained(this)));
273 drag_handler_->StartDragging(drop_data, operations, image, image_offset);
276 void WebContentsViewWin::UpdateDragCursor(WebKit::WebDragOperation operation) {
277 drag_dest_->set_drag_cursor(operation);
280 void WebContentsViewWin::GotFocus() {
281 if (web_contents_->GetDelegate())
282 web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
285 void WebContentsViewWin::TakeFocus(bool reverse) {
286 if (web_contents_->GetDelegate() &&
287 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
288 delegate_.get()) {
289 delegate_->TakeFocus(reverse);
293 void WebContentsViewWin::EndDragging() {
294 drag_handler_ = NULL;
295 web_contents_->SystemDragEnded();
298 void WebContentsViewWin::CloseTab() {
299 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
300 rvh->GetDelegate()->Close(rvh);
303 LRESULT WebContentsViewWin::OnCreate(
304 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
305 hwnd_to_wcv_map.insert(std::make_pair(hwnd(), this));
306 AddFilterToParentHwndSubclass(hwnd(), hwnd_message_filter_.get());
307 return 0;
310 LRESULT WebContentsViewWin::OnDestroy(
311 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
312 if (drag_dest_) {
313 RevokeDragDrop(GetNativeView());
314 drag_dest_ = NULL;
316 if (drag_handler_) {
317 drag_handler_->CancelDrag();
318 drag_handler_ = NULL;
320 return 0;
323 LRESULT WebContentsViewWin::OnWindowPosChanged(
324 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
326 // Our parent might have changed. So we re-install our hwnd message filter.
327 AddFilterToParentHwndSubclass(hwnd(), hwnd_message_filter_.get());
329 WINDOWPOS* window_pos = reinterpret_cast<WINDOWPOS*>(lparam);
330 if (window_pos->flags & SWP_HIDEWINDOW) {
331 web_contents_->WasHidden();
332 return 0;
335 // The WebContents was shown by a means other than the user selecting a
336 // Tab, e.g. the window was minimized then restored.
337 if (window_pos->flags & SWP_SHOWWINDOW)
338 web_contents_->WasShown();
340 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
341 if (rwhv) {
342 RenderWidgetHostViewWin* view = static_cast<RenderWidgetHostViewWin*>(rwhv);
343 view->UpdateScreenInfo(view->GetNativeView());
346 // Unless we were specifically told not to size, cause the renderer to be
347 // sized to the new bounds, which forces a repaint. Not required for the
348 // simple minimize-restore case described above, for example, since the
349 // size hasn't changed.
350 if (window_pos->flags & SWP_NOSIZE)
351 return 0;
353 gfx::Size size(window_pos->cx, window_pos->cy);
354 if (web_contents_->GetInterstitialPage())
355 web_contents_->GetInterstitialPage()->SetSize(size);
356 if (rwhv)
357 rwhv->SetSize(size);
359 if (delegate_)
360 delegate_->SizeChanged(size);
362 return 0;
365 LRESULT WebContentsViewWin::OnMouseDown(
366 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
367 // Make sure this WebContents is activated when it is clicked on.
368 if (web_contents_->GetDelegate())
369 web_contents_->GetDelegate()->ActivateContents(web_contents_);
370 return 0;
373 LRESULT WebContentsViewWin::OnMouseMove(
374 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
375 // Let our delegate know that the mouse moved (useful for resetting status
376 // bubble state).
377 if (web_contents_->GetDelegate()) {
378 web_contents_->GetDelegate()->ContentsMouseEvent(
379 web_contents_,
380 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(),
381 true);
383 return 0;
386 LRESULT WebContentsViewWin::OnNCCalcSize(
387 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
388 // Hack for ThinkPad mouse wheel driver. We have set the fake scroll bars
389 // to receive scroll messages from ThinkPad touch-pad driver. Suppress
390 // painting of scrollbars by returning 0 size for them.
391 return 0;
394 LRESULT WebContentsViewWin::OnNCHitTest(
395 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
396 return HTTRANSPARENT;
399 LRESULT WebContentsViewWin::OnScroll(
400 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
401 int scroll_type = LOWORD(wparam);
402 short position = HIWORD(wparam);
403 HWND scrollbar = reinterpret_cast<HWND>(lparam);
404 // This window can receive scroll events as a result of the ThinkPad's
405 // touch-pad scroll wheel emulation.
406 // If ctrl is held, zoom the UI. There are three issues with this:
407 // 1) Should the event be eaten or forwarded to content? We eat the event,
408 // which is like Firefox and unlike IE.
409 // 2) Should wheel up zoom in or out? We zoom in (increase font size), which
410 // is like IE and Google maps, but unlike Firefox.
411 // 3) Should the mouse have to be over the content area? We zoom as long as
412 // content has focus, although FF and IE require that the mouse is over
413 // content. This is because all events get forwarded when content has
414 // focus.
415 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
416 int distance = 0;
417 switch (scroll_type) {
418 case SB_LINEUP:
419 distance = WHEEL_DELTA;
420 break;
421 case SB_LINEDOWN:
422 distance = -WHEEL_DELTA;
423 break;
424 // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION,
425 // and SB_THUMBTRACK for completeness
426 default:
427 break;
430 web_contents_->GetDelegate()->ContentsZoomChange(distance > 0);
431 return 0;
434 // Reflect scroll message to the view() to give it a chance
435 // to process scrolling.
436 SendMessage(GetContentNativeView(), message, wparam, lparam);
437 return 0;
440 LRESULT WebContentsViewWin::OnSize(
441 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
442 // NOTE: Because we handle OnWindowPosChanged without calling DefWindowProc,
443 // OnSize is NOT called on window resize. This handler is called only once
444 // when the window is created.
445 // Don't call base class OnSize to avoid useless layout for 0x0 size.
446 // We will get OnWindowPosChanged later and layout root view in WasSized.
448 // Hack for ThinkPad touch-pad driver.
449 // Set fake scrollbars so that we can get scroll messages,
450 SCROLLINFO si = {0};
451 si.cbSize = sizeof(si);
452 si.fMask = SIF_ALL;
454 si.nMin = 1;
455 si.nMax = 100;
456 si.nPage = 10;
457 si.nPos = 50;
459 ::SetScrollInfo(hwnd(), SB_HORZ, &si, FALSE);
460 ::SetScrollInfo(hwnd(), SB_VERT, &si, FALSE);
462 return 1;
465 } // namespace content