Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / tab_contents / chrome_web_contents_view_delegate_views.cc
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.
4
5 #include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h"
6
7 #include "chrome/browser/browser_shutdown.h"
8 #include "chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.h"
9 #include "chrome/browser/ui/sad_tab_helper.h"
10 #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
11 #include "chrome/browser/ui/views/sad_tab_view.h"
12 #include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "components/web_modal/web_contents_modal_dialog_manager.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/render_widget_host_view.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/web_contents_delegate.h"
20 #include "content/public/browser/web_contents_view.h"
21 #include "ui/aura/client/screen_position_client.h"
22 #include "ui/aura/window.h"
23 #include "ui/views/focus/focus_manager.h"
24 #include "ui/views/focus/view_storage.h"
25 #include "ui/views/widget/widget.h"
26
27 using web_modal::WebContentsModalDialogManager;
28
29 ChromeWebContentsViewDelegateViews::ChromeWebContentsViewDelegateViews(
30     content::WebContents* web_contents)
31     : web_contents_(web_contents) {
32   last_focused_view_storage_id_ =
33       views::ViewStorage::GetInstance()->CreateStorageID();
34 }
35
36 ChromeWebContentsViewDelegateViews::~ChromeWebContentsViewDelegateViews() {
37   // Makes sure to remove any stored view we may still have in the ViewStorage.
38   //
39   // It is possible the view went away before us, so we only do this if the
40   // view is registered.
41   views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
42   if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
43     view_storage->RemoveView(last_focused_view_storage_id_);
44 }
45
46 content::WebDragDestDelegate*
47     ChromeWebContentsViewDelegateViews::GetDragDestDelegate() {
48   // We install a chrome specific handler to intercept bookmark drags for the
49   // bookmark manager/extension API.
50   bookmark_handler_.reset(new WebDragBookmarkHandlerAura);
51   return bookmark_handler_.get();
52 }
53
54 bool ChromeWebContentsViewDelegateViews::Focus() {
55   SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_);
56   if (sad_tab_helper) {
57     SadTabView* sad_tab = static_cast<SadTabView*>(sad_tab_helper->sad_tab());
58     if (sad_tab) {
59       sad_tab->RequestFocus();
60       return true;
61     }
62   }
63
64   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
65       WebContentsModalDialogManager::FromWebContents(web_contents_);
66   if (web_contents_modal_dialog_manager) {
67     // TODO(erg): WebContents used to own web contents modal dialogs, which is
68     // why this is here. Eventually this should be ported to a containing view
69     // specializing in web contents modal dialog management.
70     if (web_contents_modal_dialog_manager->IsDialogActive()) {
71       web_contents_modal_dialog_manager->FocusTopmostDialog();
72       return true;
73     }
74   }
75
76   return false;
77 }
78
79 void ChromeWebContentsViewDelegateViews::TakeFocus(bool reverse) {
80   views::FocusManager* focus_manager = GetFocusManager();
81   if (focus_manager)
82     focus_manager->AdvanceFocus(reverse);
83 }
84
85 void ChromeWebContentsViewDelegateViews::StoreFocus() {
86   views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
87
88   if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
89     view_storage->RemoveView(last_focused_view_storage_id_);
90
91   if (!GetFocusManager())
92     return;
93   views::View* focused_view = GetFocusManager()->GetFocusedView();
94   if (focused_view)
95     view_storage->StoreView(last_focused_view_storage_id_, focused_view);
96 }
97
98 void ChromeWebContentsViewDelegateViews::RestoreFocus() {
99   views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
100   views::View* last_focused_view =
101       view_storage->RetrieveView(last_focused_view_storage_id_);
102
103   if (!last_focused_view) {
104     SetInitialFocus();
105   } else {
106     if (last_focused_view->IsFocusable() &&
107         GetFocusManager()->ContainsView(last_focused_view)) {
108       last_focused_view->RequestFocus();
109     } else {
110       // The focused view may not belong to the same window hierarchy (e.g.
111       // if the location bar was focused and the tab is dragged out), or it may
112       // no longer be focusable (e.g. if the location bar was focused and then
113       // we switched to fullscreen mode).  In that case we default to the
114       // default focus.
115       SetInitialFocus();
116     }
117     view_storage->RemoveView(last_focused_view_storage_id_);
118   }
119 }
120
121 void ChromeWebContentsViewDelegateViews::ShowContextMenu(
122     const content::ContextMenuParams& params) {
123   // Menus need a Widget to work. If we're not the active tab we won't
124   // necessarily be in a widget.
125   views::Widget* top_level_widget = GetTopLevelWidget();
126   if (!top_level_widget)
127     return;
128
129   context_menu_.reset(
130       RenderViewContextMenuViews::Create(web_contents_, params));
131   context_menu_->Init();
132
133   // Don't show empty menus.
134   if (context_menu_->menu_model().GetItemCount() == 0)
135     return;
136
137   gfx::Point screen_point(params.x, params.y);
138
139   // Convert from content coordinates to window coordinates.
140   aura::Window* web_contents_window =
141       web_contents_->GetView()->GetNativeView();
142   aura::Window* root_window = web_contents_window->GetRootWindow();
143   aura::client::ScreenPositionClient* screen_position_client =
144       aura::client::GetScreenPositionClient(root_window);
145   if (screen_position_client) {
146     screen_position_client->ConvertPointToScreen(web_contents_window,
147                                                  &screen_point);
148   }
149   // Enable recursive tasks on the message loop so we can get updates while
150   // the context menu is being displayed.
151   base::MessageLoop::ScopedNestableTaskAllower allow(
152       base::MessageLoop::current());
153   context_menu_->RunMenuAt(top_level_widget, screen_point, params.source_type);
154 }
155
156 void ChromeWebContentsViewDelegateViews::SizeChanged(const gfx::Size& size) {
157   SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_);
158   if (!sad_tab_helper)
159     return;
160   SadTabView* sad_tab = static_cast<SadTabView*>(sad_tab_helper->sad_tab());
161   if (sad_tab)
162     sad_tab->GetWidget()->SetBounds(gfx::Rect(size));
163 }
164
165 views::Widget* ChromeWebContentsViewDelegateViews::GetTopLevelWidget() {
166   return views::Widget::GetTopLevelWidgetForNativeView(
167       web_contents_->GetView()->GetNativeView());
168 }
169
170 views::FocusManager*
171     ChromeWebContentsViewDelegateViews::GetFocusManager() {
172   views::Widget* toplevel_widget = GetTopLevelWidget();
173   return toplevel_widget ? toplevel_widget->GetFocusManager() : NULL;
174 }
175
176 void ChromeWebContentsViewDelegateViews::SetInitialFocus() {
177   if (web_contents_->FocusLocationBarByDefault()) {
178     if (web_contents_->GetDelegate())
179       web_contents_->GetDelegate()->SetFocusToLocationBar(false);
180   } else {
181     web_contents_->GetView()->Focus();
182   }
183 }
184
185 namespace chrome {
186
187 content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
188     content::WebContents* web_contents) {
189   return new ChromeWebContentsViewDelegateViews(web_contents);
190 }
191
192 }  // namespace chrome