Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2011 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.
      4 
      5 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/command_line.h"
     10 #include "base/i18n/rtl.h"
     11 #include "base/metrics/histogram.h"
     12 #include "base/process_util.h"
     13 #include "base/threading/thread.h"
     14 #include "base/win/scoped_comptr.h"
     15 #include "base/win/scoped_gdi_object.h"
     16 #include "base/win/wrapped_window_proc.h"
     17 #include "chrome/browser/accessibility/browser_accessibility_manager.h"
     18 #include "chrome/browser/accessibility/browser_accessibility_state.h"
     19 #include "chrome/browser/accessibility/browser_accessibility_win.h"
     20 #include "chrome/browser/browser_trial.h"
     21 #include "chrome/common/chrome_constants.h"
     22 #include "chrome/common/chrome_switches.h"
     23 #include "chrome/common/render_messages.h"
     24 #include "content/browser/browser_thread.h"
     25 #include "content/browser/plugin_process_host.h"
     26 #include "content/browser/renderer_host/backing_store.h"
     27 #include "content/browser/renderer_host/backing_store_win.h"
     28 #include "content/browser/renderer_host/render_process_host.h"
     29 #include "content/browser/renderer_host/render_widget_host.h"
     30 #include "content/common/native_web_keyboard_event.h"
     31 #include "content/common/notification_service.h"
     32 #include "content/common/plugin_messages.h"
     33 #include "content/common/view_messages.h"
     34 #include "grit/webkit_resources.h"
     35 #include "skia/ext/skia_utils_win.h"
     36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
     37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
     38 #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
     39 #include "ui/base/ime/composition_text.h"
     40 #include "ui/base/l10n/l10n_util.h"
     41 #include "ui/base/l10n/l10n_util_win.h"
     42 #include "ui/base/resource/resource_bundle.h"
     43 #include "ui/base/view_prop.h"
     44 #include "ui/base/win/hwnd_util.h"
     45 #include "ui/gfx/canvas.h"
     46 #include "ui/gfx/canvas_skia.h"
     47 #include "ui/gfx/gdi_util.h"
     48 #include "ui/gfx/rect.h"
     49 #include "views/accessibility/native_view_accessibility_win.h"
     50 #include "views/focus/focus_manager.h"
     51 #include "views/focus/focus_util_win.h"
     52 // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h!
     53 #include "views/widget/widget_win.h"
     54 #include "webkit/glue/webaccessibility.h"
     55 #include "webkit/glue/webcursor.h"
     56 #include "webkit/plugins/npapi/plugin_constants_win.h"
     57 #include "webkit/plugins/npapi/webplugin.h"
     58 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
     59 
     60 using base::TimeDelta;
     61 using base::TimeTicks;
     62 using ui::ViewProp;
     63 using WebKit::WebInputEvent;
     64 using WebKit::WebInputEventFactory;
     65 using WebKit::WebMouseEvent;
     66 using WebKit::WebTextDirection;
     67 using webkit::npapi::WebPluginGeometry;
     68 
     69 const wchar_t kRenderWidgetHostHWNDClass[] = L"Chrome_RenderWidgetHostHWND";
     70 
     71 namespace {
     72 
     73 // Tooltips will wrap after this width. Yes, wrap. Imagine that!
     74 const int kTooltipMaxWidthPixels = 300;
     75 
     76 // Maximum number of characters we allow in a tooltip.
     77 const int kMaxTooltipLength = 1024;
     78 
     79 // A custom MSAA object id used to determine if a screen reader is actively
     80 // listening for MSAA events.
     81 const int kIdCustom = 1;
     82 
     83 // The delay before the compositor host window is destroyed. This gives the GPU
     84 // process a grace period to stop referencing it.
     85 const int kDestroyCompositorHostWindowDelay = 10000;
     86 
     87 const char* const kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__";
     88 
     89 // A callback function for EnumThreadWindows to enumerate and dismiss
     90 // any owned popop windows
     91 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
     92   const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
     93 
     94   if (::IsWindowVisible(window)) {
     95     const HWND owner = ::GetWindow(window, GW_OWNER);
     96     if (toplevel_hwnd == owner) {
     97       ::PostMessage(window, WM_CANCELMODE, 0, 0);
     98     }
     99   }
    100 
    101   return TRUE;
    102 }
    103 
    104 class NotifyPluginProcessHostTask : public Task {
    105  public:
    106   NotifyPluginProcessHostTask(HWND window, HWND parent)
    107     : window_(window), parent_(parent), tries_(kMaxTries) { }
    108 
    109  private:
    110   void Run() {
    111     DWORD plugin_process_id;
    112     bool found_starting_plugin_process = false;
    113     GetWindowThreadProcessId(window_, &plugin_process_id);
    114     for (BrowserChildProcessHost::Iterator iter(
    115              ChildProcessInfo::PLUGIN_PROCESS);
    116          !iter.Done(); ++iter) {
    117       PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
    118       if (!plugin->handle()) {
    119         found_starting_plugin_process = true;
    120         continue;
    121       }
    122       if (base::GetProcId(plugin->handle()) == plugin_process_id) {
    123         plugin->AddWindow(parent_);
    124         return;
    125       }
    126     }
    127 
    128     if (found_starting_plugin_process) {
    129       // A plugin process has started but we don't have its handle yet.  Since
    130       // it's most likely the one for this plugin, try a few more times after a
    131       // delay.
    132       if (tries_--) {
    133         MessageLoop::current()->PostDelayedTask(FROM_HERE, this, kTryDelayMs);
    134         return;
    135       }
    136     }
    137 
    138     // The plugin process might have died in the time to execute the task, don't
    139     // leak the HWND.
    140     PostMessage(parent_, WM_CLOSE, 0, 0);
    141   }
    142 
    143   HWND window_;  // Plugin HWND, created and destroyed in the plugin process.
    144   HWND parent_;  // Parent HWND, created and destroyed on the browser UI thread.
    145 
    146   int tries_;
    147 
    148   // How many times we try to find a PluginProcessHost whose process matches
    149   // the HWND.
    150   static const int kMaxTries = 5;
    151   // How long to wait between each try.
    152   static const int kTryDelayMs = 200;
    153 };
    154 
    155 // Windows callback for OnDestroy to detach the plugin windows.
    156 BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) {
    157   if (webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(window) &&
    158       !IsHungAppWindow(window)) {
    159     ::ShowWindow(window, SW_HIDE);
    160     SetParent(window, NULL);
    161   }
    162   return TRUE;
    163 }
    164 
    165 // Draw the contents of |backing_store_dc| onto |paint_rect| with a 70% grey
    166 // filter.
    167 void DrawDeemphasized(const SkColor& color,
    168                       const gfx::Rect& paint_rect,
    169                       HDC backing_store_dc,
    170                       HDC paint_dc) {
    171   gfx::CanvasSkia canvas(paint_rect.width(), paint_rect.height(), true);
    172   HDC dc = canvas.beginPlatformPaint();
    173   BitBlt(dc,
    174          0,
    175          0,
    176          paint_rect.width(),
    177          paint_rect.height(),
    178          backing_store_dc,
    179          paint_rect.x(),
    180          paint_rect.y(),
    181          SRCCOPY);
    182   canvas.endPlatformPaint();
    183   canvas.FillRectInt(color, 0, 0, paint_rect.width(), paint_rect.height());
    184   canvas.getTopPlatformDevice().drawToHDC(paint_dc, paint_rect.x(),
    185                                           paint_rect.y(), NULL);
    186 }
    187 
    188 // The plugin wrapper window which lives in the browser process has this proc
    189 // as its window procedure. We only handle the WM_PARENTNOTIFY message sent by
    190 // windowed plugins for mouse input. This is forwarded off to the wrappers
    191 // parent which is typically the RVH window which turns on user gesture.
    192 LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
    193                                          WPARAM wparam, LPARAM lparam) {
    194   if (message == WM_PARENTNOTIFY) {
    195     switch (LOWORD(wparam)) {
    196       case WM_LBUTTONDOWN:
    197       case WM_RBUTTONDOWN:
    198       case WM_MBUTTONDOWN:
    199         ::SendMessage(GetParent(window), message, wparam, lparam);
    200         return 0;
    201       default:
    202         break;
    203     }
    204   }
    205   return ::DefWindowProc(window, message, wparam, lparam);
    206 }
    207 
    208 }  // namespace
    209 
    210 // RenderWidgetHostView --------------------------------------------------------
    211 
    212 // static
    213 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
    214     RenderWidgetHost* widget) {
    215   return new RenderWidgetHostViewWin(widget);
    216 }
    217 
    218 ///////////////////////////////////////////////////////////////////////////////
    219 // RenderWidgetHostViewWin, public:
    220 
    221 RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
    222     : render_widget_host_(widget),
    223       compositor_host_window_(NULL),
    224       hide_compositor_window_at_next_paint_(false),
    225       track_mouse_leave_(false),
    226       ime_notification_(false),
    227       capture_enter_key_(false),
    228       is_hidden_(false),
    229       about_to_validate_and_paint_(false),
    230       close_on_deactivate_(false),
    231       being_destroyed_(false),
    232       tooltip_hwnd_(NULL),
    233       tooltip_showing_(false),
    234       shutdown_factory_(this),
    235       parent_hwnd_(NULL),
    236       is_loading_(false),
    237       overlay_color_(0),
    238       text_input_type_(WebKit::WebTextInputTypeNone) {
    239   render_widget_host_->set_view(this);
    240   registrar_.Add(this,
    241                  NotificationType::RENDERER_PROCESS_TERMINATED,
    242                  NotificationService::AllSources());
    243 }
    244 
    245 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
    246   ResetTooltip();
    247 }
    248 
    249 void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
    250   Create(parent);  // ATL function to create the window.
    251 }
    252 
    253 ///////////////////////////////////////////////////////////////////////////////
    254 // RenderWidgetHostViewWin, RenderWidgetHostView implementation:
    255 
    256 void RenderWidgetHostViewWin::InitAsPopup(
    257     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
    258   parent_hwnd_ = parent_host_view->GetNativeView();
    259   close_on_deactivate_ = true;
    260   Create(parent_hwnd_, NULL, NULL, WS_POPUP, WS_EX_TOOLWINDOW);
    261   MoveWindow(pos.x(), pos.y(), pos.width(), pos.height(), TRUE);
    262   // Popups are not activated.
    263   ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
    264 }
    265 
    266 void RenderWidgetHostViewWin::InitAsFullscreen() {
    267   NOTIMPLEMENTED() << "Fullscreen not implemented on Win";
    268 }
    269 
    270 RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const {
    271   return render_widget_host_;
    272 }
    273 
    274 void RenderWidgetHostViewWin::DidBecomeSelected() {
    275   if (!is_hidden_)
    276     return;
    277 
    278   if (tab_switch_paint_time_.is_null())
    279     tab_switch_paint_time_ = TimeTicks::Now();
    280   is_hidden_ = false;
    281   EnsureTooltip();
    282   render_widget_host_->WasRestored();
    283 }
    284 
    285 void RenderWidgetHostViewWin::WasHidden() {
    286   if (is_hidden_)
    287     return;
    288 
    289   // If we receive any more paint messages while we are hidden, we want to
    290   // ignore them so we don't re-allocate the backing store.  We will paint
    291   // everything again when we become selected again.
    292   is_hidden_ = true;
    293 
    294   ResetTooltip();
    295 
    296   // If we have a renderer, then inform it that we are being hidden so it can
    297   // reduce its resource utilization.
    298   render_widget_host_->WasHidden();
    299 
    300   // TODO(darin): what about constrained windows?  it doesn't look like they
    301   // see a message when their parent is hidden.  maybe there is something more
    302   // generic we can do at the TabContents API level instead of relying on
    303   // Windows messages.
    304 }
    305 
    306 void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) {
    307   SetBounds(gfx::Rect(GetViewBounds().origin(), size));
    308 }
    309 
    310 void RenderWidgetHostViewWin::SetBounds(const gfx::Rect& rect) {
    311   if (is_hidden_)
    312     return;
    313 
    314   // No SWP_NOREDRAW as autofill popups can move and the underneath window
    315   // should redraw in that case.
    316   UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS |
    317       SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE;
    318 
    319   // If the style is not popup, you have to convert the point to client
    320   // coordinate.
    321   POINT point = { rect.x(), rect.y() };
    322   if (GetStyle() & WS_CHILD)
    323     ScreenToClient(&point);
    324 
    325   SetWindowPos(NULL, point.x, point.y, rect.width(), rect.height(), swp_flags);
    326   render_widget_host_->WasResized();
    327   EnsureTooltip();
    328 }
    329 
    330 gfx::NativeView RenderWidgetHostViewWin::GetNativeView() {
    331   return m_hWnd;
    332 }
    333 
    334 void RenderWidgetHostViewWin::MovePluginWindows(
    335     const std::vector<WebPluginGeometry>& plugin_window_moves) {
    336   if (plugin_window_moves.empty())
    337     return;
    338 
    339   bool oop_plugins =
    340     !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
    341     !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins);
    342 
    343   HDWP defer_window_pos_info =
    344       ::BeginDeferWindowPos(static_cast<int>(plugin_window_moves.size()));
    345 
    346   if (!defer_window_pos_info) {
    347     NOTREACHED();
    348     return;
    349   }
    350 
    351   for (size_t i = 0; i < plugin_window_moves.size(); ++i) {
    352     unsigned long flags = 0;
    353     const WebPluginGeometry& move = plugin_window_moves[i];
    354     HWND window = move.window;
    355 
    356     // As the plugin parent window which lives on the browser UI thread is
    357     // destroyed asynchronously, it is possible that we have a stale window
    358     // sent in by the renderer for moving around.
    359     // Note: get the parent before checking if the window is valid, to avoid a
    360     // race condition where the window is destroyed after the check but before
    361     // the GetParent call.
    362     HWND parent = ::GetParent(window);
    363     if (!::IsWindow(window))
    364       continue;
    365 
    366     if (oop_plugins) {
    367       if (parent == m_hWnd) {
    368         // The plugin window is a direct child of this window, add an
    369         // intermediate window that lives on this thread to speed up scrolling.
    370         // Note this only works with out of process plugins since we depend on
    371         // PluginProcessHost to destroy the intermediate HWNDs.
    372         parent = ReparentWindow(window);
    373         ::ShowWindow(window, SW_SHOW);  // Window was created hidden.
    374       } else if (::GetParent(parent) != m_hWnd) {
    375         // The renderer should only be trying to move windows that are children
    376         // of its render widget window. However, this may happen as a result of
    377         // a race condition, so we ignore it and not kill the plugin process.
    378         continue;
    379       }
    380 
    381       // We move the intermediate parent window which doesn't result in cross-
    382       // process synchronous Windows messages.
    383       window = parent;
    384     }
    385 
    386     if (move.visible)
    387       flags |= SWP_SHOWWINDOW;
    388     else
    389       flags |= SWP_HIDEWINDOW;
    390 
    391     if (move.rects_valid) {
    392       HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(),
    393                                   move.clip_rect.y(),
    394                                   move.clip_rect.right(),
    395                                   move.clip_rect.bottom());
    396       gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
    397 
    398       // Note: System will own the hrgn after we call SetWindowRgn,
    399       // so we don't need to call DeleteObject(hrgn)
    400       ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());
    401     } else {
    402       flags |= SWP_NOMOVE;
    403       flags |= SWP_NOSIZE;
    404     }
    405 
    406     defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
    407                                              window, NULL,
    408                                              move.window_rect.x(),
    409                                              move.window_rect.y(),
    410                                              move.window_rect.width(),
    411                                              move.window_rect.height(), flags);
    412     if (!defer_window_pos_info) {
    413       DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
    414       return;
    415     }
    416   }
    417 
    418   ::EndDeferWindowPos(defer_window_pos_info);
    419 }
    420 
    421 HWND RenderWidgetHostViewWin::ReparentWindow(HWND window) {
    422   static ATOM window_class = 0;
    423   if (!window_class) {
    424     WNDCLASSEX wcex;
    425     wcex.cbSize         = sizeof(WNDCLASSEX);
    426     wcex.style          = CS_DBLCLKS;
    427     wcex.lpfnWndProc    = base::win::WrappedWindowProc<PluginWrapperWindowProc>;
    428     wcex.cbClsExtra     = 0;
    429     wcex.cbWndExtra     = 0;
    430     wcex.hInstance      = GetModuleHandle(NULL);
    431     wcex.hIcon          = 0;
    432     wcex.hCursor        = 0;
    433     wcex.hbrBackground  = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
    434     wcex.lpszMenuName   = 0;
    435     wcex.lpszClassName  = webkit::npapi::kWrapperNativeWindowClassName;
    436     wcex.hIconSm        = 0;
    437     window_class = RegisterClassEx(&wcex);
    438   }
    439   DCHECK(window_class);
    440 
    441   HWND parent = CreateWindowEx(
    442       WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
    443       MAKEINTATOM(window_class), 0,
    444       WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
    445       0, 0, 0, 0, ::GetParent(window), 0, GetModuleHandle(NULL), 0);
    446   ui::CheckWindowCreated(parent);
    447   ::SetParent(window, parent);
    448   BrowserThread::PostTask(
    449       BrowserThread::IO, FROM_HERE,
    450       new NotifyPluginProcessHostTask(window, parent));
    451   return parent;
    452 }
    453 
    454 static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) {
    455   std::vector<HWND>* vector = reinterpret_cast<std::vector<HWND>*>(lparam);
    456   vector->push_back(hwnd);
    457   return TRUE;
    458 }
    459 
    460 void RenderWidgetHostViewWin::CleanupCompositorWindow() {
    461   if (!compositor_host_window_)
    462     return;
    463 
    464   // Hide the compositor and parent it to the desktop rather than destroying
    465   // it immediately. The GPU process has a grace period to stop accessing the
    466   // window. TODO(apatrick): the GPU process should acknowledge that it has
    467   // finished with the window handle and the browser process should destroy it
    468   // at that point.
    469   ::ShowWindow(compositor_host_window_, SW_HIDE);
    470   ::SetParent(compositor_host_window_, NULL);
    471 
    472   BrowserThread::PostDelayedTask(
    473       BrowserThread::UI,
    474       FROM_HERE,
    475       NewRunnableFunction(::DestroyWindow, compositor_host_window_),
    476       kDestroyCompositorHostWindowDelay);
    477 
    478   compositor_host_window_ = NULL;
    479 }
    480 
    481 bool RenderWidgetHostViewWin::IsActivatable() const {
    482   // Popups should not be activated.
    483   return popup_type_ == WebKit::WebPopupTypeNone;
    484 }
    485 
    486 void RenderWidgetHostViewWin::Focus() {
    487   if (IsWindow())
    488     SetFocus();
    489 }
    490 
    491 void RenderWidgetHostViewWin::Blur() {
    492   views::FocusManager* focus_manager =
    493       views::FocusManager::GetFocusManagerForNativeView(m_hWnd);
    494   // We don't have a FocusManager if we are hidden.
    495   if (focus_manager)
    496     focus_manager->ClearFocus();
    497 }
    498 
    499 bool RenderWidgetHostViewWin::HasFocus() {
    500   return ::GetFocus() == m_hWnd;
    501 }
    502 
    503 void RenderWidgetHostViewWin::Show() {
    504   DCHECK(parent_hwnd_);
    505   DCHECK(parent_hwnd_ != GetDesktopWindow());
    506   SetParent(parent_hwnd_);
    507   ShowWindow(SW_SHOW);
    508 
    509   // Save away our HWND in the parent window as a property so that the
    510   // accessibility code can find it.
    511   accessibility_prop_.reset(new ViewProp(
    512       GetParent(),
    513       views::kViewsNativeHostPropForAccessibility,
    514       m_hWnd));
    515 
    516   DidBecomeSelected();
    517 }
    518 
    519 void RenderWidgetHostViewWin::Hide() {
    520   if (GetParent() == GetDesktopWindow()) {
    521     LOG(WARNING) << "Hide() called twice in a row: " << this << ":" <<
    522         parent_hwnd_ << ":" << GetParent();
    523     return;
    524   }
    525 
    526   accessibility_prop_.reset();
    527 
    528   if (::GetFocus() == m_hWnd)
    529     ::SetFocus(NULL);
    530   ShowWindow(SW_HIDE);
    531 
    532   // Cache the old parent, then orphan the window so we stop receiving messages
    533   parent_hwnd_ = GetParent();
    534   SetParent(NULL);
    535 
    536   WasHidden();
    537 }
    538 
    539 bool RenderWidgetHostViewWin::IsShowing() {
    540   return !!IsWindowVisible();
    541 }
    542 
    543 gfx::Rect RenderWidgetHostViewWin::GetViewBounds() const {
    544   CRect window_rect;
    545   GetWindowRect(&window_rect);
    546   return gfx::Rect(window_rect);
    547 }
    548 
    549 void RenderWidgetHostViewWin::UpdateCursor(const WebCursor& cursor) {
    550   current_cursor_ = cursor;
    551   UpdateCursorIfOverSelf();
    552 }
    553 
    554 void RenderWidgetHostViewWin::UpdateCursorIfOverSelf() {
    555   static HCURSOR kCursorArrow = LoadCursor(NULL, IDC_ARROW);
    556   static HCURSOR kCursorAppStarting = LoadCursor(NULL, IDC_APPSTARTING);
    557   static HINSTANCE module_handle =
    558       GetModuleHandle(chrome::kBrowserResourcesDll);
    559 
    560   // If the mouse is over our HWND, then update the cursor state immediately.
    561   CPoint pt;
    562   GetCursorPos(&pt);
    563   if (WindowFromPoint(pt) == m_hWnd) {
    564     BOOL result = ::ScreenToClient(m_hWnd, &pt);
    565     DCHECK(result);
    566     // We cannot pass in NULL as the module handle as this would only work for
    567     // standard win32 cursors. We can also receive cursor types which are
    568     // defined as webkit resources. We need to specify the module handle of
    569     // chrome.dll while loading these cursors.
    570     HCURSOR display_cursor = current_cursor_.GetCursor(module_handle);
    571 
    572     // If a page is in the loading state, we want to show the Arrow+Hourglass
    573     // cursor only when the current cursor is the ARROW cursor. In all other
    574     // cases we should continue to display the current cursor.
    575     if (is_loading_ && display_cursor == kCursorArrow)
    576       display_cursor = kCursorAppStarting;
    577 
    578     SetCursor(display_cursor);
    579   }
    580 }
    581 
    582 void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) {
    583   is_loading_ = is_loading;
    584   UpdateCursorIfOverSelf();
    585 }
    586 
    587 void RenderWidgetHostViewWin::ImeUpdateTextInputState(
    588     WebKit::WebTextInputType type,
    589     const gfx::Rect& caret_rect) {
    590   if (text_input_type_ != type) {
    591     text_input_type_ = type;
    592     if (type == WebKit::WebTextInputTypeText)
    593       ime_input_.EnableIME(m_hWnd);
    594     else
    595       ime_input_.DisableIME(m_hWnd);
    596   }
    597 
    598   // Only update caret position if the input method is enabled.
    599   if (type == WebKit::WebTextInputTypeText)
    600     ime_input_.UpdateCaretRect(m_hWnd, caret_rect);
    601 }
    602 
    603 void RenderWidgetHostViewWin::ImeCancelComposition() {
    604   ime_input_.CancelIME(m_hWnd);
    605 }
    606 
    607 BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) {
    608   if (!webkit::npapi::WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd))
    609     return TRUE;
    610 
    611   gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
    612   static UINT msg = RegisterWindowMessage(webkit::npapi::kPaintMessageName);
    613   WPARAM wparam = rect->x() << 16 | rect->y();
    614   lparam = rect->width() << 16 | rect->height();
    615 
    616   // SendMessage gets the message across much quicker than PostMessage, since it
    617   // doesn't get queued.  When the plugin thread calls PeekMessage or other
    618   // Win32 APIs, sent messages are dispatched automatically.
    619   SendNotifyMessage(hwnd, msg, wparam, lparam);
    620 
    621   return TRUE;
    622 }
    623 
    624 void RenderWidgetHostViewWin::Redraw() {
    625   RECT damage_bounds;
    626   GetUpdateRect(&damage_bounds, FALSE);
    627 
    628   base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
    629   GetUpdateRgn(damage_region, FALSE);
    630 
    631   // Paint the invalid region synchronously.  Our caller will not paint again
    632   // until we return, so by painting to the screen here, we ensure effective
    633   // rate-limiting of backing store updates.  This helps a lot on pages that
    634   // have animations or fairly expensive layout (e.g., google maps).
    635   //
    636   // We paint this window synchronously, however child windows (i.e. plugins)
    637   // are painted asynchronously.  By avoiding synchronous cross-process window
    638   // message dispatching we allow scrolling to be smooth, and also avoid the
    639   // browser process locking up if the plugin process is hung.
    640   //
    641   RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN);
    642 
    643   // Send the invalid rect in screen coordinates.
    644   gfx::Rect screen_rect = GetViewBounds();
    645   gfx::Rect invalid_screen_rect(damage_bounds);
    646   invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
    647 
    648   LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect);
    649   EnumChildWindows(m_hWnd, EnumChildProc, lparam);
    650 }
    651 
    652 void RenderWidgetHostViewWin::DidUpdateBackingStore(
    653     const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
    654     const std::vector<gfx::Rect>& copy_rects) {
    655   if (is_hidden_)
    656     return;
    657 
    658   // Schedule invalidations first so that the ScrollWindowEx call is closer to
    659   // Redraw.  That minimizes chances of "flicker" resulting if the screen
    660   // refreshes before we have a chance to paint the exposed area.  Somewhat
    661   // surprisingly, this ordering matters.
    662 
    663   for (size_t i = 0; i < copy_rects.size(); ++i)
    664     InvalidateRect(&copy_rects[i].ToRECT(), false);
    665 
    666   if (!scroll_rect.IsEmpty()) {
    667     RECT clip_rect = scroll_rect.ToRECT();
    668     ScrollWindowEx(scroll_dx, scroll_dy, NULL, &clip_rect, NULL, NULL,
    669                    SW_INVALIDATE);
    670   }
    671 
    672   if (!about_to_validate_and_paint_)
    673     Redraw();
    674 }
    675 
    676 void RenderWidgetHostViewWin::RenderViewGone(base::TerminationStatus status,
    677                                              int error_code) {
    678   // TODO(darin): keep this around, and draw sad-tab into it.
    679   UpdateCursorIfOverSelf();
    680   being_destroyed_ = true;
    681   CleanupCompositorWindow();
    682   DestroyWindow();
    683 }
    684 
    685 void RenderWidgetHostViewWin::WillWmDestroy() {
    686   CleanupCompositorWindow();
    687 }
    688 
    689 void RenderWidgetHostViewWin::WillDestroyRenderWidget(RenderWidgetHost* rwh) {
    690   if (rwh == render_widget_host_)
    691     render_widget_host_ = NULL;
    692 }
    693 
    694 void RenderWidgetHostViewWin::Destroy() {
    695   // We've been told to destroy.
    696   // By clearing close_on_deactivate_, we prevent further deactivations
    697   // (caused by windows messages resulting from the DestroyWindow) from
    698   // triggering further destructions.  The deletion of this is handled by
    699   // OnFinalMessage();
    700   close_on_deactivate_ = false;
    701   being_destroyed_ = true;
    702   CleanupCompositorWindow();
    703   DestroyWindow();
    704 }
    705 
    706 void RenderWidgetHostViewWin::SetTooltipText(const std::wstring& tooltip_text) {
    707   // Clamp the tooltip length to kMaxTooltipLength so that we don't
    708   // accidentally DOS the user with a mega tooltip (since Windows doesn't seem
    709   // to do this itself).
    710   const std::wstring& new_tooltip_text =
    711       l10n_util::TruncateString(tooltip_text, kMaxTooltipLength);
    712 
    713   if (new_tooltip_text != tooltip_text_) {
    714     tooltip_text_ = new_tooltip_text;
    715 
    716     // Need to check if the tooltip is already showing so that we don't
    717     // immediately show the tooltip with no delay when we move the mouse from
    718     // a region with no tooltip to a region with a tooltip.
    719     if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) {
    720       ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
    721       ::SendMessage(tooltip_hwnd_, TTM_POPUP, 0, 0);
    722     }
    723   } else {
    724     // Make sure the tooltip gets closed after TTN_POP gets sent. For some
    725     // reason this doesn't happen automatically, so moving the mouse around
    726     // within the same link/image/etc doesn't cause the tooltip to re-appear.
    727     if (!tooltip_showing_) {
    728       if (::IsWindow(tooltip_hwnd_))
    729         ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
    730     }
    731   }
    732 }
    733 
    734 BackingStore* RenderWidgetHostViewWin::AllocBackingStore(
    735     const gfx::Size& size) {
    736   return new BackingStoreWin(render_widget_host_, size);
    737 }
    738 
    739 void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) {
    740   RenderWidgetHostView::SetBackground(background);
    741   Send(new ViewMsg_SetBackground(render_widget_host_->routing_id(),
    742                                  background));
    743 }
    744 
    745 bool RenderWidgetHostViewWin::ContainsNativeView(
    746     gfx::NativeView native_view) const {
    747   if (m_hWnd == native_view)
    748     return true;
    749 
    750   // Traverse the set of parents of the given view to determine if native_view
    751   // is a descendant of this window.
    752   HWND parent_window = ::GetParent(native_view);
    753   while (parent_window) {
    754     if (parent_window == m_hWnd)
    755       return true;
    756     parent_window = ::GetParent(parent_window);
    757   }
    758 
    759   return false;
    760 }
    761 
    762 void RenderWidgetHostViewWin::SetVisuallyDeemphasized(const SkColor* color,
    763                                                       bool animate) {
    764   // |animate| is not yet implemented, and currently isn't used.
    765   CHECK(!animate);
    766 
    767   SkColor overlay_color = color ? *color : 0;
    768   if (overlay_color_ == overlay_color)
    769     return;
    770   overlay_color_ = overlay_color;
    771 
    772   InvalidateRect(NULL, FALSE);
    773 }
    774 
    775 ///////////////////////////////////////////////////////////////////////////////
    776 // RenderWidgetHostViewWin, private:
    777 
    778 LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) {
    779   // Call the WM_INPUTLANGCHANGE message handler to initialize the input locale
    780   // of a browser process.
    781   OnInputLangChange(0, 0);
    782   // Marks that window as supporting mouse-wheel messages rerouting so it is
    783   // scrolled when under the mouse pointer even if inactive.
    784   props_.push_back(views::SetWindowSupportsRerouteMouseWheel(m_hWnd));
    785   props_.push_back(new ViewProp(m_hWnd, kRenderWidgetHostViewKey,
    786                                 static_cast<RenderWidgetHostView*>(this)));
    787   // Save away our HWND in the parent window as a property so that the
    788   // accessibility code can find it.
    789   accessibility_prop_.reset(new ViewProp(
    790       GetParent(),
    791       views::kViewsNativeHostPropForAccessibility,
    792       m_hWnd));
    793 
    794   return 0;
    795 }
    796 
    797 void RenderWidgetHostViewWin::OnActivate(UINT action, BOOL minimized,
    798                                          HWND window) {
    799   // If the container is a popup, clicking elsewhere on screen should close the
    800   // popup.
    801   if (close_on_deactivate_ && action == WA_INACTIVE) {
    802     // Send a windows message so that any derived classes
    803     // will get a change to override the default handling
    804     SendMessage(WM_CANCELMODE);
    805   }
    806 }
    807 
    808 void RenderWidgetHostViewWin::OnDestroy() {
    809   // When a tab is closed all its child plugin windows are destroyed
    810   // automatically. This happens before plugins get any notification that its
    811   // instances are tearing down.
    812   //
    813   // Plugins like Quicktime assume that their windows will remain valid as long
    814   // as they have plugin instances active. Quicktime crashes in this case
    815   // because its windowing code cleans up an internal data structure that the
    816   // handler for NPP_DestroyStream relies on.
    817   //
    818   // The fix is to detach plugin windows from web contents when it is going
    819   // away. This will prevent the plugin windows from getting destroyed
    820   // automatically. The detached plugin windows will get cleaned up in proper
    821   // sequence as part of the usual cleanup when the plugin instance goes away.
    822   EnumChildWindows(m_hWnd, DetachPluginWindowsCallback, NULL);
    823 
    824   props_.reset();
    825 
    826   CleanupCompositorWindow();
    827 
    828   ResetTooltip();
    829   TrackMouseLeave(false);
    830 }
    831 
    832 void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
    833   DCHECK(render_widget_host_->process()->HasConnection());
    834 
    835   // If the GPU process is rendering directly into the View,
    836   // call the compositor directly.
    837   RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
    838   if (render_widget_host->is_accelerated_compositing_active()) {
    839     // We initialize paint_dc here so that BeginPaint()/EndPaint()
    840     // get called to validate the region.
    841     CPaintDC paint_dc(m_hWnd);
    842     render_widget_host_->ScheduleComposite();
    843     return;
    844   }
    845 
    846   about_to_validate_and_paint_ = true;
    847   BackingStoreWin* backing_store = static_cast<BackingStoreWin*>(
    848       render_widget_host_->GetBackingStore(true));
    849 
    850   // We initialize |paint_dc| (and thus call BeginPaint()) after calling
    851   // GetBackingStore(), so that if it updates the invalid rect we'll catch the
    852   // changes and repaint them.
    853   about_to_validate_and_paint_ = false;
    854 
    855   // Grab the region to paint before creation of paint_dc since it clears the
    856   // damage region.
    857   base::win::ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
    858   GetUpdateRgn(damage_region, FALSE);
    859 
    860   if (hide_compositor_window_at_next_paint_) {
    861     ::ShowWindow(compositor_host_window_, SW_HIDE);
    862     hide_compositor_window_at_next_paint_ = false;
    863   }
    864 
    865   CPaintDC paint_dc(m_hWnd);
    866 
    867   gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
    868   if (damaged_rect.IsEmpty())
    869     return;
    870 
    871   if (backing_store) {
    872     gfx::Rect bitmap_rect(gfx::Point(), backing_store->size());
    873 
    874     bool manage_colors = BackingStoreWin::ColorManagementEnabled();
    875     if (manage_colors)
    876       SetICMMode(paint_dc.m_hDC, ICM_ON);
    877 
    878     // Blit only the damaged regions from the backing store.
    879     DWORD data_size = GetRegionData(damage_region, 0, NULL);
    880     scoped_array<char> region_data_buf(new char[data_size]);
    881     RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
    882     GetRegionData(damage_region, data_size, region_data);
    883 
    884     RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
    885     for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
    886       gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i]));
    887       if (!paint_rect.IsEmpty()) {
    888         if (SkColorGetA(overlay_color_) > 0) {
    889           DrawDeemphasized(overlay_color_,
    890                            paint_rect,
    891                            backing_store->hdc(),
    892                            paint_dc.m_hDC);
    893         } else {
    894           BitBlt(paint_dc.m_hDC,
    895                  paint_rect.x(),
    896                  paint_rect.y(),
    897                  paint_rect.width(),
    898                  paint_rect.height(),
    899                  backing_store->hdc(),
    900                  paint_rect.x(),
    901                  paint_rect.y(),
    902                  SRCCOPY);
    903         }
    904       }
    905     }
    906 
    907     if (manage_colors)
    908       SetICMMode(paint_dc.m_hDC, ICM_OFF);
    909 
    910     // Fill the remaining portion of the damaged_rect with the background
    911     if (damaged_rect.right() > bitmap_rect.right()) {
    912       RECT r;
    913       r.left = std::max(bitmap_rect.right(), damaged_rect.x());
    914       r.right = damaged_rect.right();
    915       r.top = damaged_rect.y();
    916       r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom());
    917       DrawBackground(r, &paint_dc);
    918     }
    919     if (damaged_rect.bottom() > bitmap_rect.bottom()) {
    920       RECT r;
    921       r.left = damaged_rect.x();
    922       r.right = damaged_rect.right();
    923       r.top = std::max(bitmap_rect.bottom(), damaged_rect.y());
    924       r.bottom = damaged_rect.bottom();
    925       DrawBackground(r, &paint_dc);
    926     }
    927     if (!whiteout_start_time_.is_null()) {
    928       TimeDelta whiteout_duration = TimeTicks::Now() - whiteout_start_time_;
    929       UMA_HISTOGRAM_TIMES("MPArch.RWHH_WhiteoutDuration", whiteout_duration);
    930 
    931       // Reset the start time to 0 so that we start recording again the next
    932       // time the backing store is NULL...
    933       whiteout_start_time_ = TimeTicks();
    934     }
    935     if (!tab_switch_paint_time_.is_null()) {
    936       TimeDelta tab_switch_paint_duration = TimeTicks::Now() -
    937           tab_switch_paint_time_;
    938       UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration",
    939           tab_switch_paint_duration);
    940       // Reset tab_switch_paint_time_ to 0 so future tab selections are
    941       // recorded.
    942       tab_switch_paint_time_ = TimeTicks();
    943     }
    944   } else {
    945     DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc);
    946     if (whiteout_start_time_.is_null())
    947       whiteout_start_time_ = TimeTicks::Now();
    948   }
    949 }
    950 
    951 void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect,
    952                                              CPaintDC* dc) {
    953   if (!background_.empty()) {
    954     gfx::CanvasSkia canvas(dirty_rect.right - dirty_rect.left,
    955                            dirty_rect.bottom - dirty_rect.top,
    956                            true);  // opaque
    957     canvas.TranslateInt(-dirty_rect.left, -dirty_rect.top);
    958 
    959     const RECT& dc_rect = dc->m_ps.rcPaint;
    960     canvas.TileImageInt(background_, 0, 0,
    961                         dc_rect.right - dc_rect.left,
    962                         dc_rect.bottom - dc_rect.top);
    963 
    964     canvas.getTopPlatformDevice().drawToHDC(*dc, dirty_rect.left,
    965                                             dirty_rect.top, NULL);
    966   } else {
    967     HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    968     dc->FillRect(&dirty_rect, white_brush);
    969   }
    970 }
    971 
    972 void RenderWidgetHostViewWin::OnNCPaint(HRGN update_region) {
    973   // Do nothing.  This suppresses the resize corner that Windows would
    974   // otherwise draw for us.
    975 }
    976 
    977 LRESULT RenderWidgetHostViewWin::OnEraseBkgnd(HDC dc) {
    978   return 1;
    979 }
    980 
    981 LRESULT RenderWidgetHostViewWin::OnSetCursor(HWND window, UINT hittest_code,
    982                                              UINT mouse_message_id) {
    983   UpdateCursorIfOverSelf();
    984   return 0;
    985 }
    986 
    987 void RenderWidgetHostViewWin::OnSetFocus(HWND window) {
    988   views::FocusManager::GetWidgetFocusManager()->OnWidgetFocusEvent(window,
    989                                                                    m_hWnd);
    990   if (browser_accessibility_manager_.get())
    991     browser_accessibility_manager_->GotFocus();
    992   if (render_widget_host_)
    993     render_widget_host_->GotFocus();
    994 }
    995 
    996 void RenderWidgetHostViewWin::OnKillFocus(HWND window) {
    997   views::FocusManager::GetWidgetFocusManager()->OnWidgetFocusEvent(m_hWnd,
    998                                                                    window);
    999 
   1000   if (render_widget_host_)
   1001     render_widget_host_->Blur();
   1002 }
   1003 
   1004 void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) {
   1005   if (render_widget_host_)
   1006     render_widget_host_->LostCapture();
   1007 }
   1008 
   1009 void RenderWidgetHostViewWin::OnCancelMode() {
   1010   if (render_widget_host_)
   1011     render_widget_host_->LostCapture();
   1012 
   1013   if (close_on_deactivate_ && shutdown_factory_.empty()) {
   1014     // Dismiss popups and menus.  We do this asynchronously to avoid changing
   1015     // activation within this callstack, which may interfere with another window
   1016     // being activated.  We can synchronously hide the window, but we need to
   1017     // not change activation while doing so.
   1018     SetWindowPos(NULL, 0, 0, 0, 0,
   1019                  SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
   1020                  SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
   1021     MessageLoop::current()->PostTask(FROM_HERE,
   1022         shutdown_factory_.NewRunnableMethod(
   1023             &RenderWidgetHostViewWin::ShutdownHost));
   1024   }
   1025 }
   1026 
   1027 void RenderWidgetHostViewWin::OnInputLangChange(DWORD character_set,
   1028                                                 HKL input_language_id) {
   1029   // Send the given Locale ID to the ImeInput object and retrieves whether
   1030   // or not the current input context has IMEs.
   1031   // If the current input context has IMEs, a browser process has to send a
   1032   // request to a renderer process that it needs status messages about
   1033   // the focused edit control from the renderer process.
   1034   // On the other hand, if the current input context does not have IMEs, the
   1035   // browser process also has to send a request to the renderer process that
   1036   // it does not need the status messages any longer.
   1037   // To minimize the number of this notification request, we should check if
   1038   // the browser process is actually retrieving the status messages (this
   1039   // state is stored in ime_notification_) and send a request only if the
   1040   // browser process has to update this status, its details are listed below:
   1041   // * If a browser process is not retrieving the status messages,
   1042   //   (i.e. ime_notification_ == false),
   1043   //   send this request only if the input context does have IMEs,
   1044   //   (i.e. ime_status == true);
   1045   //   When it successfully sends the request, toggle its notification status,
   1046   //   (i.e.ime_notification_ = !ime_notification_ = true).
   1047   // * If a browser process is retrieving the status messages
   1048   //   (i.e. ime_notification_ == true),
   1049   //   send this request only if the input context does not have IMEs,
   1050   //   (i.e. ime_status == false).
   1051   //   When it successfully sends the request, toggle its notification status,
   1052   //   (i.e.ime_notification_ = !ime_notification_ = false).
   1053   // To analyze the above actions, we can optimize them into the ones
   1054   // listed below:
   1055   // 1 Sending a request only if ime_status_ != ime_notification_, and;
   1056   // 2 Copying ime_status to ime_notification_ if it sends the request
   1057   //   successfully (because Action 1 shows ime_status = !ime_notification_.)
   1058   bool ime_status = ime_input_.SetInputLanguage();
   1059   if (ime_status != ime_notification_) {
   1060     if (render_widget_host_) {
   1061       render_widget_host_->SetInputMethodActive(ime_status);
   1062       ime_notification_ = ime_status;
   1063     }
   1064   }
   1065 }
   1066 
   1067 void RenderWidgetHostViewWin::OnThemeChanged() {
   1068   if (render_widget_host_)
   1069     render_widget_host_->SystemThemeChanged();
   1070 }
   1071 
   1072 LRESULT RenderWidgetHostViewWin::OnNotify(int w_param, NMHDR* header) {
   1073   if (tooltip_hwnd_ == NULL)
   1074     return 0;
   1075 
   1076   switch (header->code) {
   1077     case TTN_GETDISPINFO: {
   1078       NMTTDISPINFOW* tooltip_info = reinterpret_cast<NMTTDISPINFOW*>(header);
   1079       tooltip_info->szText[0] = L'\0';
   1080       tooltip_info->lpszText = const_cast<wchar_t*>(tooltip_text_.c_str());
   1081       ::SendMessage(
   1082         tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels);
   1083       SetMsgHandled(TRUE);
   1084       break;
   1085                           }
   1086     case TTN_POP:
   1087       tooltip_showing_ = false;
   1088       SetMsgHandled(TRUE);
   1089       break;
   1090     case TTN_SHOW:
   1091       tooltip_showing_ = true;
   1092       SetMsgHandled(TRUE);
   1093       break;
   1094   }
   1095   return 0;
   1096 }
   1097 
   1098 LRESULT RenderWidgetHostViewWin::OnImeSetContext(
   1099     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
   1100   if (!render_widget_host_)
   1101     return 0;
   1102 
   1103   // We need status messages about the focused input control from a
   1104   // renderer process when:
   1105   //   * the current input context has IMEs, and;
   1106   //   * an application is activated.
   1107   // This seems to tell we should also check if the current input context has
   1108   // IMEs before sending a request, however, this WM_IME_SETCONTEXT is
   1109   // fortunately sent to an application only while the input context has IMEs.
   1110   // Therefore, we just start/stop status messages according to the activation
   1111   // status of this application without checks.
   1112   bool activated = (wparam == TRUE);
   1113   if (render_widget_host_) {
   1114     render_widget_host_->SetInputMethodActive(activated);
   1115     ime_notification_ = activated;
   1116   }
   1117 
   1118   if (ime_notification_)
   1119     ime_input_.CreateImeWindow(m_hWnd);
   1120 
   1121   ime_input_.CleanupComposition(m_hWnd);
   1122   return ime_input_.SetImeWindowStyle(
   1123       m_hWnd, message, wparam, lparam, &handled);
   1124 }
   1125 
   1126 LRESULT RenderWidgetHostViewWin::OnImeStartComposition(
   1127     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
   1128   if (!render_widget_host_)
   1129     return 0;
   1130 
   1131   // Reset the composition status and create IME windows.
   1132   ime_input_.CreateImeWindow(m_hWnd);
   1133   ime_input_.ResetComposition(m_hWnd);
   1134   // We have to prevent WTL from calling ::DefWindowProc() because the function
   1135   // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
   1136   // over-write the position of IME windows.
   1137   handled = TRUE;
   1138   return 0;
   1139 }
   1140 
   1141 LRESULT RenderWidgetHostViewWin::OnImeComposition(
   1142     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
   1143   if (!render_widget_host_)
   1144     return 0;
   1145 
   1146   // At first, update the position of the IME window.
   1147   ime_input_.UpdateImeWindow(m_hWnd);
   1148 
   1149   // ui::CompositionUnderline should be identical to
   1150   // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
   1151   COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
   1152                  sizeof(WebKit::WebCompositionUnderline),
   1153                  ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
   1154 
   1155   // Retrieve the result string and its attributes of the ongoing composition
   1156   // and send it to a renderer process.
   1157   ui::CompositionText composition;
   1158   if (ime_input_.GetResult(m_hWnd, lparam, &composition.text)) {
   1159     render_widget_host_->ImeConfirmComposition(composition.text);
   1160     ime_input_.ResetComposition(m_hWnd);
   1161     // Fall though and try reading the composition string.
   1162     // Japanese IMEs send a message containing both GCS_RESULTSTR and
   1163     // GCS_COMPSTR, which means an ongoing composition has been finished
   1164     // by the start of another composition.
   1165   }
   1166   // Retrieve the composition string and its attributes of the ongoing
   1167   // composition and send it to a renderer process.
   1168   if (ime_input_.GetComposition(m_hWnd, lparam, &composition)) {
   1169     // TODO(suzhe): due to a bug of webkit, we can't use selection range with
   1170     // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
   1171     composition.selection = ui::Range(composition.selection.end());
   1172 
   1173     // TODO(suzhe): convert both renderer_host and renderer to use
   1174     // ui::CompositionText.
   1175     const std::vector<WebKit::WebCompositionUnderline>& underlines =
   1176         reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
   1177             composition.underlines);
   1178     render_widget_host_->ImeSetComposition(
   1179         composition.text, underlines,
   1180         composition.selection.start(), composition.selection.end());
   1181   }
   1182   // We have to prevent WTL from calling ::DefWindowProc() because we do not
   1183   // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
   1184   handled = TRUE;
   1185   return 0;
   1186 }
   1187 
   1188 LRESULT RenderWidgetHostViewWin::OnImeEndComposition(
   1189     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
   1190   if (!render_widget_host_)
   1191     return 0;
   1192 
   1193   if (ime_input_.is_composing()) {
   1194     // A composition has been ended while there is an ongoing composition,
   1195     // i.e. the ongoing composition has been canceled.
   1196     // We need to reset the composition status both of the ImeInput object and
   1197     // of the renderer process.
   1198     render_widget_host_->ImeCancelComposition();
   1199     ime_input_.ResetComposition(m_hWnd);
   1200   }
   1201   ime_input_.DestroyImeWindow(m_hWnd);
   1202   // Let WTL call ::DefWindowProc() and release its resources.
   1203   handled = FALSE;
   1204   return 0;
   1205 }
   1206 
   1207 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam,
   1208                                               LPARAM lparam, BOOL& handled) {
   1209   handled = TRUE;
   1210 
   1211   if (::IsWindow(tooltip_hwnd_)) {
   1212     // Forward mouse events through to the tooltip window
   1213     MSG msg;
   1214     msg.hwnd = m_hWnd;
   1215     msg.message = message;
   1216     msg.wParam = wparam;
   1217     msg.lParam = lparam;
   1218     SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL,
   1219                 reinterpret_cast<LPARAM>(&msg));
   1220   }
   1221 
   1222   // TODO(jcampan): I am not sure if we should forward the message to the
   1223   // TabContents first in the case of popups.  If we do, we would need to
   1224   // convert the click from the popup window coordinates to the TabContents'
   1225   // window coordinates. For now we don't forward the message in that case to
   1226   // address bug #907474.
   1227   // Note: GetParent() on popup windows returns the top window and not the
   1228   // parent the window was created with (the parent and the owner of the popup
   1229   // is the first non-child view of the view that was specified to the create
   1230   // call).  So the TabContents window would have to be specified to the
   1231   // RenderViewHostHWND as there is no way to retrieve it from the HWND.
   1232   if (!close_on_deactivate_) {  // Don't forward if the container is a popup.
   1233     switch (message) {
   1234       case WM_LBUTTONDOWN:
   1235       case WM_MBUTTONDOWN:
   1236       case WM_RBUTTONDOWN:
   1237         // Finish the ongoing composition whenever a mouse click happens.
   1238         // It matches IE's behavior.
   1239         ime_input_.CleanupComposition(m_hWnd);
   1240         // Fall through.
   1241       case WM_MOUSEMOVE:
   1242       case WM_MOUSELEAVE: {
   1243         // Give the TabContents first crack at the message. It may want to
   1244         // prevent forwarding to the renderer if some higher level browser
   1245         // functionality is invoked.
   1246         LPARAM parent_msg_lparam = lparam;
   1247         if (message != WM_MOUSELEAVE) {
   1248           // For the messages except WM_MOUSELEAVE, before forwarding them to
   1249           // parent window, we should adjust cursor position from client
   1250           // coordinates in current window to client coordinates in its parent
   1251           // window.
   1252           CPoint cursor_pos(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
   1253           ClientToScreen(&cursor_pos);
   1254           GetParent().ScreenToClient(&cursor_pos);
   1255           parent_msg_lparam = MAKELPARAM(cursor_pos.x, cursor_pos.y);
   1256         }
   1257         if (SendMessage(GetParent(), message, wparam, parent_msg_lparam) != 0)
   1258           return 1;
   1259       }
   1260     }
   1261   }
   1262 
   1263   ForwardMouseEventToRenderer(message, wparam, lparam);
   1264   return 0;
   1265 }
   1266 
   1267 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
   1268                                             LPARAM lparam, BOOL& handled) {
   1269   handled = TRUE;
   1270 
   1271   // If we are a pop-up, forward tab related messages to our parent HWND, so
   1272   // that we are dismissed appropriately and so that the focus advance in our
   1273   // parent.
   1274   // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the
   1275   //                FocusManager.
   1276   if (close_on_deactivate_ &&
   1277       (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) ||
   1278         (message == WM_CHAR && wparam == L'\t'))) {
   1279     DCHECK(parent_hwnd_);
   1280     // First close the pop-up.
   1281     SendMessage(WM_CANCELMODE);
   1282     // Then move the focus by forwarding the tab key to the parent.
   1283     return ::SendMessage(parent_hwnd_, message, wparam, lparam);
   1284   }
   1285 
   1286   if (!render_widget_host_)
   1287     return 0;
   1288 
   1289   // Bug 1845: we need to update the text direction when a user releases
   1290   // either a right-shift key or a right-control key after pressing both of
   1291   // them. So, we just update the text direction while a user is pressing the
   1292   // keys, and we notify the text direction when a user releases either of them.
   1293   // Bug 9718: http://crbug.com/9718 To investigate IE and notepad, this
   1294   // shortcut is enabled only on a PC having RTL keyboard layouts installed.
   1295   // We should emulate them.
   1296   if (ui::ImeInput::IsRTLKeyboardLayoutInstalled()) {
   1297     if (message == WM_KEYDOWN) {
   1298       if (wparam == VK_SHIFT) {
   1299         base::i18n::TextDirection dir;
   1300         if (ui::ImeInput::IsCtrlShiftPressed(&dir)) {
   1301           render_widget_host_->UpdateTextDirection(
   1302               dir == base::i18n::RIGHT_TO_LEFT ?
   1303               WebKit::WebTextDirectionRightToLeft :
   1304               WebKit::WebTextDirectionLeftToRight);
   1305         }
   1306       } else if (wparam != VK_CONTROL) {
   1307         // Bug 9762: http://crbug.com/9762 A user pressed a key except shift
   1308         // and control keys.
   1309         // When a user presses a key while he/she holds control and shift keys,
   1310         // we cancel sending an IPC message in NotifyTextDirection() below and
   1311         // ignore succeeding UpdateTextDirection() calls while we call
   1312         // NotifyTextDirection().
   1313         // To cancel it, this call set a flag that prevents sending an IPC
   1314         // message in NotifyTextDirection() only if we are going to send it.
   1315         // It is harmless to call this function if we aren't going to send it.
   1316         render_widget_host_->CancelUpdateTextDirection();
   1317       }
   1318     } else if (message == WM_KEYUP &&
   1319                (wparam == VK_SHIFT || wparam == VK_CONTROL)) {
   1320       // We send an IPC message only if we need to update the text direction.
   1321       render_widget_host_->NotifyTextDirection();
   1322     }
   1323   }
   1324 
   1325   // Special processing for enter key: When user hits enter in omnibox
   1326   // we change focus to render host after the navigation, so repeat WM_KEYDOWNs
   1327   // and WM_KEYUP are going to render host, despite being initiated in other
   1328   // window. This code filters out these messages.
   1329   bool ignore_keyboard_event = false;
   1330   if (wparam == VK_RETURN) {
   1331     if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) {
   1332       if (KF_REPEAT & HIWORD(lparam)) {
   1333         // this is a repeated key
   1334         if (!capture_enter_key_)
   1335           ignore_keyboard_event = true;
   1336       } else {
   1337         capture_enter_key_ = true;
   1338       }
   1339     } else if (message == WM_KEYUP || message == WM_SYSKEYUP) {
   1340       if (!capture_enter_key_)
   1341         ignore_keyboard_event = true;
   1342       capture_enter_key_ = false;
   1343     } else {
   1344       // Ignore all other keyboard events for the enter key if not captured.
   1345       if (!capture_enter_key_)
   1346         ignore_keyboard_event = true;
   1347     }
   1348   }
   1349 
   1350   if (render_widget_host_ && !ignore_keyboard_event) {
   1351     render_widget_host_->ForwardKeyboardEvent(
   1352         NativeWebKeyboardEvent(m_hWnd, message, wparam, lparam));
   1353   }
   1354   return 0;
   1355 }
   1356 
   1357 LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
   1358                                               LPARAM lparam, BOOL& handled) {
   1359   // Forward the mouse-wheel message to the window under the mouse if it belongs
   1360   // to us.
   1361   if (message == WM_MOUSEWHEEL &&
   1362       views::RerouteMouseWheel(m_hWnd, wparam, lparam)) {
   1363     handled = TRUE;
   1364     return 0;
   1365   }
   1366 
   1367   // Workaround for Thinkpad mousewheel driver. We get mouse wheel/scroll
   1368   // messages even if we are not in the foreground. So here we check if
   1369   // we have any owned popup windows in the foreground and dismiss them.
   1370   if (m_hWnd != GetForegroundWindow()) {
   1371     HWND toplevel_hwnd = ::GetAncestor(m_hWnd, GA_ROOT);
   1372     EnumThreadWindows(
   1373         GetCurrentThreadId(),
   1374         DismissOwnedPopups,
   1375         reinterpret_cast<LPARAM>(toplevel_hwnd));
   1376   }
   1377 
   1378   // This is a bit of a hack, but will work for now since we don't want to
   1379   // pollute this object with TabContents-specific functionality...
   1380   bool handled_by_TabContents = false;
   1381   if (GetParent()) {
   1382     // Use a special reflected message to break recursion. If we send
   1383     // WM_MOUSEWHEEL, the focus manager subclass of web contents will
   1384     // route it back here.
   1385     MSG new_message = {0};
   1386     new_message.hwnd = m_hWnd;
   1387     new_message.message = message;
   1388     new_message.wParam = wparam;
   1389     new_message.lParam = lparam;
   1390 
   1391     handled_by_TabContents =
   1392         !!::SendMessage(GetParent(), views::kReflectedMessage, 0,
   1393                         reinterpret_cast<LPARAM>(&new_message));
   1394   }
   1395 
   1396   if (!handled_by_TabContents && render_widget_host_) {
   1397     render_widget_host_->ForwardWheelEvent(
   1398         WebInputEventFactory::mouseWheelEvent(m_hWnd, message, wparam,
   1399                                               lparam));
   1400   }
   1401   handled = TRUE;
   1402   return 0;
   1403 }
   1404 
   1405 LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message,
   1406                                                  WPARAM wparam,
   1407                                                  LPARAM lparam,
   1408                                                  BOOL& handled) {
   1409   if (!IsActivatable())
   1410     return MA_NOACTIVATE;
   1411 
   1412   HWND focus_window = GetFocus();
   1413   if (!::IsWindow(focus_window) || !IsChild(focus_window)) {
   1414     // We handle WM_MOUSEACTIVATE to set focus to the underlying plugin
   1415     // child window. This is to ensure that keyboard events are received
   1416     // by the plugin. The correct way to fix this would be send over
   1417     // an event to the renderer which would then eventually send over
   1418     // a setFocus call to the plugin widget. This would ensure that
   1419     // the renderer (webkit) knows about the plugin widget receiving
   1420     // focus.
   1421     // TODO(iyengar) Do the right thing as per the above comment.
   1422     POINT cursor_pos = {0};
   1423     ::GetCursorPos(&cursor_pos);
   1424     ::ScreenToClient(m_hWnd, &cursor_pos);
   1425     HWND child_window = ::RealChildWindowFromPoint(m_hWnd, cursor_pos);
   1426     if (::IsWindow(child_window) && child_window != m_hWnd) {
   1427       if (ui::GetClassName(child_window) ==
   1428               webkit::npapi::kWrapperNativeWindowClassName)
   1429         child_window = ::GetWindow(child_window, GW_CHILD);
   1430 
   1431       ::SetFocus(child_window);
   1432       return MA_NOACTIVATE;
   1433     }
   1434   }
   1435   handled = FALSE;
   1436   render_widget_host_->OnMouseActivate();
   1437   return MA_ACTIVATE;
   1438 }
   1439 
   1440 void RenderWidgetHostViewWin::OnAccessibilityNotifications(
   1441     const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
   1442   if (!browser_accessibility_manager_.get()) {
   1443     // Use empty document to process notifications
   1444     webkit_glue::WebAccessibility empty_document;
   1445     empty_document.role = WebAccessibility::ROLE_DOCUMENT;
   1446     empty_document.state = 0;
   1447     browser_accessibility_manager_.reset(
   1448         BrowserAccessibilityManager::Create(m_hWnd, empty_document, this));
   1449   }
   1450 
   1451   browser_accessibility_manager_->OnAccessibilityNotifications(params);
   1452 }
   1453 
   1454 void RenderWidgetHostViewWin::Observe(NotificationType type,
   1455                                       const NotificationSource& source,
   1456                                       const NotificationDetails& details) {
   1457   DCHECK(type == NotificationType::RENDERER_PROCESS_TERMINATED);
   1458 
   1459   // Get the RenderProcessHost that posted this notification, and exit
   1460   // if it's not the one associated with this host view.
   1461   RenderProcessHost* render_process_host =
   1462       Source<RenderProcessHost>(source).ptr();
   1463   DCHECK(render_process_host);
   1464   if (!render_widget_host_ ||
   1465       render_process_host != render_widget_host_->process())
   1466     return;
   1467 
   1468   // If it was our RenderProcessHost that posted the notification,
   1469   // clear the BrowserAccessibilityManager, because the renderer is
   1470   // dead and any accessibility information we have is now stale.
   1471   browser_accessibility_manager_.reset(NULL);
   1472 }
   1473 
   1474 static void PaintCompositorHostWindow(HWND hWnd) {
   1475   PAINTSTRUCT paint;
   1476   BeginPaint(hWnd, &paint);
   1477 
   1478   EndPaint(hWnd, &paint);
   1479 }
   1480 
   1481 // WndProc for the compositor host window. We use this instead of Default so
   1482 // we can drop WM_PAINT and WM_ERASEBKGD messages on the floor.
   1483 static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message,
   1484                                                  WPARAM wParam, LPARAM lParam) {
   1485   switch (message) {
   1486   case WM_ERASEBKGND:
   1487     return 0;
   1488   case WM_DESTROY:
   1489     return 0;
   1490   case WM_PAINT:
   1491     PaintCompositorHostWindow(hWnd);
   1492     return 0;
   1493   default:
   1494     return DefWindowProc(hWnd, message, wParam, lParam);
   1495   }
   1496 }
   1497 
   1498 // Creates a HWND within the RenderWidgetHostView that will serve as a host
   1499 // for a HWND that the GPU process will create. The host window is used
   1500 // to Z-position the GPU's window relative to other plugin windows.
   1501 gfx::PluginWindowHandle RenderWidgetHostViewWin::GetCompositingSurface() {
   1502   // If the window has been created, don't recreate it a second time
   1503   if (compositor_host_window_)
   1504     return compositor_host_window_;
   1505 
   1506   static ATOM window_class = 0;
   1507   if (!window_class) {
   1508     WNDCLASSEX wcex;
   1509     wcex.cbSize         = sizeof(WNDCLASSEX);
   1510     wcex.style          = 0;
   1511     wcex.lpfnWndProc    =
   1512         base::win::WrappedWindowProc<CompositorHostWindowProc>;
   1513     wcex.cbClsExtra     = 0;
   1514     wcex.cbWndExtra     = 0;
   1515     wcex.hInstance      = GetModuleHandle(NULL);
   1516     wcex.hIcon          = 0;
   1517     wcex.hCursor        = 0;
   1518     wcex.hbrBackground  = NULL;
   1519     wcex.lpszMenuName   = 0;
   1520     wcex.lpszClassName  = L"CompositorHostWindowClass";
   1521     wcex.hIconSm        = 0;
   1522     window_class = RegisterClassEx(&wcex);
   1523     DCHECK(window_class);
   1524   }
   1525 
   1526   RECT currentRect;
   1527   GetClientRect(&currentRect);
   1528   int width = currentRect.right - currentRect.left;
   1529   int height = currentRect.bottom - currentRect.top;
   1530 
   1531   compositor_host_window_ = CreateWindowEx(
   1532     WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
   1533     MAKEINTATOM(window_class), 0,
   1534     WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
   1535     0, 0, width, height, m_hWnd, 0, GetModuleHandle(NULL), 0);
   1536   ui::CheckWindowCreated(compositor_host_window_);
   1537 
   1538   return static_cast<gfx::PluginWindowHandle>(compositor_host_window_);
   1539 }
   1540 
   1541 void RenderWidgetHostViewWin::ShowCompositorHostWindow(bool show) {
   1542   // When we first create the compositor, we will get a show request from
   1543   // the renderer before we have gotten the create request from the GPU. In this
   1544   // case, simply ignore the show request.
   1545   if (compositor_host_window_ == NULL)
   1546     return;
   1547 
   1548   if (show) {
   1549     ::ShowWindow(compositor_host_window_, SW_SHOW);
   1550 
   1551     // Get all the child windows of this view, including the compositor window.
   1552     std::vector<HWND> all_child_windows;
   1553     ::EnumChildWindows(m_hWnd, AddChildWindowToVector,
   1554         reinterpret_cast<LPARAM>(&all_child_windows));
   1555 
   1556     // Build a list of just the plugin window handles
   1557     std::vector<HWND> plugin_windows;
   1558     bool compositor_host_window_found = false;
   1559     for (size_t i = 0; i < all_child_windows.size(); ++i) {
   1560       if (all_child_windows[i] != compositor_host_window_)
   1561         plugin_windows.push_back(all_child_windows[i]);
   1562       else
   1563         compositor_host_window_found = true;
   1564     }
   1565     DCHECK(compositor_host_window_found);
   1566 
   1567     // Set all the plugin windows to be "after" the compositor window.
   1568     // When the compositor window is created, gets placed above plugins.
   1569     for (size_t i = 0; i < plugin_windows.size(); ++i) {
   1570       HWND next;
   1571       if (i + 1 < plugin_windows.size())
   1572         next = plugin_windows[i+1];
   1573       else
   1574         next = compositor_host_window_;
   1575       ::SetWindowPos(plugin_windows[i], next, 0, 0, 0, 0,
   1576           SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
   1577     }
   1578   } else {
   1579     hide_compositor_window_at_next_paint_ = true;
   1580   }
   1581 }
   1582 
   1583 void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) {
   1584   if (!browser_accessibility_manager_.get() ||
   1585       !render_widget_host_ ||
   1586       !render_widget_host_->process() ||
   1587       !render_widget_host_->process()->HasConnection()) {
   1588     return;
   1589   }
   1590 
   1591   render_widget_host_->SetAccessibilityFocus(acc_obj_id);
   1592 }
   1593 
   1594 void RenderWidgetHostViewWin::AccessibilityDoDefaultAction(int acc_obj_id) {
   1595   if (!browser_accessibility_manager_.get() ||
   1596       !render_widget_host_ ||
   1597       !render_widget_host_->process() ||
   1598       !render_widget_host_->process()->HasConnection()) {
   1599     return;
   1600   }
   1601 
   1602   render_widget_host_->AccessibilityDoDefaultAction(acc_obj_id);
   1603 }
   1604 
   1605 LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam,
   1606                                              LPARAM lparam, BOOL& handled) {
   1607   if (kIdCustom == lparam) {
   1608     // An MSAA client requestes our custom id. Assume that we have detected an
   1609     // active windows screen reader.
   1610     BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
   1611     render_widget_host_->EnableRendererAccessibility();
   1612 
   1613     // Return with failure.
   1614     return static_cast<LRESULT>(0L);
   1615   }
   1616 
   1617   if (lparam != OBJID_CLIENT) {
   1618     handled = false;
   1619     return static_cast<LRESULT>(0L);
   1620   }
   1621 
   1622   if (render_widget_host_ && !render_widget_host_->renderer_accessible()) {
   1623     // Attempt to detect screen readers by sending an event with our custom id.
   1624     NotifyWinEvent(EVENT_SYSTEM_ALERT, m_hWnd, kIdCustom, CHILDID_SELF);
   1625   }
   1626 
   1627   if (!browser_accessibility_manager_.get()) {
   1628     // Return busy document tree while renderer accessibility tree loads.
   1629     webkit_glue::WebAccessibility loading_tree;
   1630     loading_tree.role = WebAccessibility::ROLE_DOCUMENT;
   1631     loading_tree.state = (1 << WebAccessibility::STATE_BUSY);
   1632     browser_accessibility_manager_.reset(
   1633       BrowserAccessibilityManager::Create(m_hWnd, loading_tree, this));
   1634   }
   1635 
   1636   base::win::ScopedComPtr<IAccessible> root(
   1637       browser_accessibility_manager_->GetRoot()->toBrowserAccessibilityWin());
   1638   if (root.get())
   1639     return LresultFromObject(IID_IAccessible, wparam, root.Detach());
   1640 
   1641   handled = false;
   1642   return static_cast<LRESULT>(0L);
   1643 }
   1644 
   1645 LRESULT RenderWidgetHostViewWin::OnParentNotify(UINT message, WPARAM wparam,
   1646                                                 LPARAM lparam, BOOL& handled) {
   1647   handled = FALSE;
   1648 
   1649   if (!render_widget_host_)
   1650     return 0;
   1651 
   1652   switch (LOWORD(wparam)) {
   1653     case WM_LBUTTONDOWN:
   1654     case WM_RBUTTONDOWN:
   1655     case WM_MBUTTONDOWN:
   1656       render_widget_host_->StartUserGesture();
   1657       break;
   1658     default:
   1659       break;
   1660   }
   1661   return 0;
   1662 }
   1663 
   1664 void RenderWidgetHostViewWin::OnFinalMessage(HWND window) {
   1665   // When the render widget host is being destroyed, it ends up calling
   1666   // WillDestroyRenderWidget (through the RENDER_WIDGET_HOST_DESTROYED
   1667   // notification) which NULLs render_widget_host_.
   1668   // Note: the following bug http://crbug.com/24248 seems to report that
   1669   // OnFinalMessage is called with a deleted |render_widget_host_|. It is not
   1670   // clear how this could happen, hence the NULLing of render_widget_host_
   1671   // above.
   1672   if (!render_widget_host_ && !being_destroyed_) {
   1673     // If you hit this NOTREACHED, please add a comment to report it on
   1674     // http://crbug.com/24248, including what you did when it happened and if
   1675     // you can repro.
   1676     NOTREACHED();
   1677   }
   1678   if (render_widget_host_)
   1679     render_widget_host_->ViewDestroyed();
   1680   delete this;
   1681 }
   1682 
   1683 void RenderWidgetHostViewWin::TrackMouseLeave(bool track) {
   1684   if (track == track_mouse_leave_)
   1685     return;
   1686   track_mouse_leave_ = track;
   1687 
   1688   DCHECK(m_hWnd);
   1689 
   1690   TRACKMOUSEEVENT tme;
   1691   tme.cbSize = sizeof(TRACKMOUSEEVENT);
   1692   tme.dwFlags = TME_LEAVE;
   1693   if (!track_mouse_leave_)
   1694     tme.dwFlags |= TME_CANCEL;
   1695   tme.hwndTrack = m_hWnd;
   1696 
   1697   TrackMouseEvent(&tme);
   1698 }
   1699 
   1700 bool RenderWidgetHostViewWin::Send(IPC::Message* message) {
   1701   if (!render_widget_host_)
   1702     return false;
   1703   return render_widget_host_->Send(message);
   1704 }
   1705 
   1706 void RenderWidgetHostViewWin::EnsureTooltip() {
   1707   UINT message = TTM_NEWTOOLRECT;
   1708 
   1709   TOOLINFO ti;
   1710   ti.cbSize = sizeof(ti);
   1711   ti.hwnd = m_hWnd;
   1712   ti.uId = 0;
   1713   if (!::IsWindow(tooltip_hwnd_)) {
   1714     message = TTM_ADDTOOL;
   1715     tooltip_hwnd_ = CreateWindowEx(
   1716         WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(),
   1717         TOOLTIPS_CLASS, NULL, TTS_NOPREFIX, 0, 0, 0, 0, m_hWnd, NULL,
   1718         NULL, NULL);
   1719     ui::CheckWindowCreated(tooltip_hwnd_);
   1720     ti.uFlags = TTF_TRANSPARENT;
   1721     ti.lpszText = LPSTR_TEXTCALLBACK;
   1722   }
   1723 
   1724   CRect cr;
   1725   GetClientRect(&ti.rect);
   1726   SendMessage(tooltip_hwnd_, message, NULL, reinterpret_cast<LPARAM>(&ti));
   1727 }
   1728 
   1729 void RenderWidgetHostViewWin::ResetTooltip() {
   1730   if (::IsWindow(tooltip_hwnd_))
   1731     ::DestroyWindow(tooltip_hwnd_);
   1732   tooltip_hwnd_ = NULL;
   1733 }
   1734 
   1735 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
   1736                                                           WPARAM wparam,
   1737                                                           LPARAM lparam) {
   1738   if (!render_widget_host_)
   1739     return;
   1740 
   1741   WebMouseEvent event(
   1742       WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam));
   1743 
   1744   // Send the event to the renderer before changing mouse capture, so that the
   1745   // capturelost event arrives after mouseup.
   1746   render_widget_host_->ForwardMouseEvent(event);
   1747 
   1748   switch (event.type) {
   1749     case WebInputEvent::MouseMove:
   1750       TrackMouseLeave(true);
   1751       break;
   1752     case WebInputEvent::MouseLeave:
   1753       TrackMouseLeave(false);
   1754       break;
   1755     case WebInputEvent::MouseDown:
   1756       SetCapture();
   1757       break;
   1758     case WebInputEvent::MouseUp:
   1759       if (GetCapture() == m_hWnd)
   1760         ReleaseCapture();
   1761       break;
   1762   }
   1763 
   1764   if (IsActivatable() && event.type == WebInputEvent::MouseDown) {
   1765     // This is a temporary workaround for bug 765011 to get focus when the
   1766     // mouse is clicked. This happens after the mouse down event is sent to
   1767     // the renderer because normally Windows does a WM_SETFOCUS after
   1768     // WM_LBUTTONDOWN.
   1769     SetFocus();
   1770   }
   1771 }
   1772 
   1773 void RenderWidgetHostViewWin::ShutdownHost() {
   1774   shutdown_factory_.RevokeAll();
   1775   if (render_widget_host_)
   1776     render_widget_host_->Shutdown();
   1777   // Do not touch any members at this point, |this| has been deleted.
   1778 }
   1779 
   1780 // static
   1781 RenderWidgetHostView*
   1782     RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView(
   1783         gfx::NativeView native_view) {
   1784   return ::IsWindow(native_view) ?
   1785       reinterpret_cast<RenderWidgetHostView*>(
   1786           ViewProp::GetValue(native_view, kRenderWidgetHostViewKey)) : NULL;
   1787 }
   1788