summaryrefslogtreecommitdiffstats
path: root/chromium/ui/views/controls/webview/webview.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/views/controls/webview/webview.cc')
-rw-r--r--chromium/ui/views/controls/webview/webview.cc236
1 files changed, 145 insertions, 91 deletions
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index f2ea02f48fb..21de7261231 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -10,10 +10,10 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
#include "ipc/ipc_message.h"
-#include "ui/base/accessibility/accessibility_types.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/events/event.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -29,63 +29,51 @@ const char WebView::kViewClassName[] = "WebView";
// WebView, public:
WebView::WebView(content::BrowserContext* browser_context)
- : wcv_holder_(new NativeViewHost),
- web_contents_(NULL),
+ : holder_(new NativeViewHost()),
embed_fullscreen_widget_mode_enabled_(false),
is_embedding_fullscreen_widget_(false),
browser_context_(browser_context),
allow_accelerators_(false) {
- AddChildView(wcv_holder_);
+ AddChildView(holder_); // Takes ownership of |holder_|.
NativeViewAccessibility::RegisterWebView(this);
}
WebView::~WebView() {
+ SetWebContents(NULL); // Make sure all necessary tear-down takes place.
NativeViewAccessibility::UnregisterWebView(this);
}
content::WebContents* WebView::GetWebContents() {
- CreateWebContentsWithSiteInstance(NULL);
- return web_contents_;
-}
-
-void WebView::CreateWebContentsWithSiteInstance(
- content::SiteInstance* site_instance) {
- if (!web_contents_) {
- wc_owner_.reset(CreateWebContents(browser_context_, site_instance));
- web_contents_ = wc_owner_.get();
- web_contents_->SetDelegate(this);
- AttachWebContents();
+ if (!web_contents()) {
+ wc_owner_.reset(CreateWebContents(browser_context_));
+ wc_owner_->SetDelegate(this);
+ SetWebContents(wc_owner_.get());
}
+ return web_contents();
}
-void WebView::SetWebContents(content::WebContents* web_contents) {
- if (web_contents == web_contents_)
+void WebView::SetWebContents(content::WebContents* replacement) {
+ if (replacement == web_contents())
return;
DetachWebContents();
- if (wc_owner_ != web_contents)
+ WebContentsObserver::Observe(replacement);
+ // web_contents() now returns |replacement| from here onwards.
+ if (wc_owner_ != replacement)
wc_owner_.reset();
- web_contents_ = web_contents;
if (embed_fullscreen_widget_mode_enabled_) {
is_embedding_fullscreen_widget_ =
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
+ web_contents() && web_contents()->GetFullscreenRenderWidgetHostView();
} else {
- is_embedding_fullscreen_widget_ = false;
+ DCHECK(!is_embedding_fullscreen_widget_);
}
AttachWebContents();
+ NotifyMaybeTextInputClientChanged();
}
void WebView::SetEmbedFullscreenWidgetMode(bool enable) {
- bool should_be_embedded = enable;
- if (!embed_fullscreen_widget_mode_enabled_ && enable) {
- DCHECK(!is_embedding_fullscreen_widget_);
- embed_fullscreen_widget_mode_enabled_ = true;
- should_be_embedded =
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
- } else if (embed_fullscreen_widget_mode_enabled_ && !enable) {
- embed_fullscreen_widget_mode_enabled_ = false;
- }
- if (should_be_embedded != is_embedding_fullscreen_widget_)
- ReattachForFullscreenChange(should_be_embedded);
+ DCHECK(!web_contents())
+ << "Cannot change mode while a WebContents is attached.";
+ embed_fullscreen_widget_mode_enabled_ = enable;
}
void WebView::LoadInitialURL(const GURL& url) {
@@ -95,7 +83,7 @@ void WebView::LoadInitialURL(const GURL& url) {
}
void WebView::SetFastResize(bool fast_resize) {
- wcv_holder_->set_fast_resize(fast_resize);
+ holder_->set_fast_resize(fast_resize);
}
void WebView::OnWebContentsFocused(content::WebContents* web_contents) {
@@ -116,8 +104,68 @@ const char* WebView::GetClassName() const {
return kViewClassName;
}
+ui::TextInputClient* WebView::GetTextInputClient() {
+ // This function delegates the text input handling to the underlying
+ // content::RenderWidgetHostView. So when the underlying RWHV is destroyed or
+ // replaced with another one, we have to notify the FocusManager through
+ // FocusManager::OnTextInputClientChanged() that the focused TextInputClient
+ // needs to be updated.
+ if (switches::IsTextInputFocusManagerEnabled() &&
+ web_contents() && !web_contents()->IsBeingDestroyed()) {
+ content::RenderWidgetHostView* host_view =
+ is_embedding_fullscreen_widget_ ?
+ web_contents()->GetFullscreenRenderWidgetHostView() :
+ web_contents()->GetRenderWidgetHostView();
+ if (host_view)
+ return host_view->GetTextInputClient();
+ }
+ return NULL;
+}
+
void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- wcv_holder_->SetSize(bounds().size());
+ // In most cases, the holder is simply sized to fill this WebView's bounds.
+ // Only WebContentses that are in fullscreen mode and being screen-captured
+ // will engage the special layout/sizing behavior.
+ gfx::Rect holder_bounds(bounds().size());
+ if (!embed_fullscreen_widget_mode_enabled_ ||
+ !web_contents() ||
+ web_contents()->GetCapturerCount() == 0 ||
+ web_contents()->GetPreferredSize().IsEmpty() ||
+ !(is_embedding_fullscreen_widget_ ||
+ (web_contents()->GetDelegate() &&
+ web_contents()->GetDelegate()->
+ IsFullscreenForTabOrPending(web_contents())))) {
+ holder_->SetBoundsRect(holder_bounds);
+ return;
+ }
+
+ // Size the holder to the capture video resolution and center it. If this
+ // WebView is not large enough to contain the holder at the preferred size,
+ // scale down to fit (preserving aspect ratio).
+ const gfx::Size capture_size = web_contents()->GetPreferredSize();
+ if (capture_size.width() <= holder_bounds.width() &&
+ capture_size.height() <= holder_bounds.height()) {
+ // No scaling, just centering.
+ holder_bounds.ClampToCenteredSize(capture_size);
+ } else {
+ // Scale down, preserving aspect ratio, and center.
+ // TODO(miu): This is basically media::ComputeLetterboxRegion(), and it
+ // looks like others have written this code elsewhere. Let's considate
+ // into a shared function ui/gfx/geometry or around there.
+ const int64 x = static_cast<int64>(capture_size.width()) *
+ holder_bounds.height();
+ const int64 y = static_cast<int64>(capture_size.height()) *
+ holder_bounds.width();
+ if (y < x) {
+ holder_bounds.ClampToCenteredSize(gfx::Size(
+ holder_bounds.width(), static_cast<int>(y / capture_size.width())));
+ } else {
+ holder_bounds.ClampToCenteredSize(gfx::Size(
+ static_cast<int>(x / capture_size.height()), holder_bounds.height()));
+ }
+ }
+
+ holder_->SetBoundsRect(holder_bounds);
}
void WebView::ViewHierarchyChanged(
@@ -135,48 +183,48 @@ bool WebView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
// We'll first give the page a chance to process the key events. If it does
// not process them, they'll be returned to us and we'll treat them as
// accelerators then.
- return web_contents_ && !web_contents_->IsCrashed();
+ return web_contents() && !web_contents()->IsCrashed();
}
bool WebView::IsFocusable() const {
// We need to be focusable when our contents is not a view hierarchy, as
// clicking on the contents needs to focus us.
- return !!web_contents_;
+ return !!web_contents();
}
void WebView::OnFocus() {
- if (!web_contents_)
+ if (!web_contents())
return;
if (is_embedding_fullscreen_widget_) {
content::RenderWidgetHostView* const current_fs_view =
- web_contents_->GetFullscreenRenderWidgetHostView();
+ web_contents()->GetFullscreenRenderWidgetHostView();
if (current_fs_view)
current_fs_view->Focus();
} else {
- web_contents_->GetView()->Focus();
+ web_contents()->Focus();
}
}
void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) {
- if (web_contents_)
- web_contents_->FocusThroughTabTraversal(reverse);
+ if (web_contents())
+ web_contents()->FocusThroughTabTraversal(reverse);
}
-void WebView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_GROUPING;
+void WebView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_GROUP;
}
gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
- if (web_contents_) {
+ if (web_contents()) {
content::RenderWidgetHostView* host_view =
- web_contents_->GetRenderWidgetHostView();
+ web_contents()->GetRenderWidgetHostView();
if (host_view)
return host_view->GetNativeViewAccessible();
}
return View::GetNativeViewAccessible();
}
-gfx::Size WebView::GetPreferredSize() {
+gfx::Size WebView::GetPreferredSize() const {
if (preferred_size_ == gfx::Size())
return View::GetPreferredSize();
else
@@ -189,7 +237,7 @@ gfx::Size WebView::GetPreferredSize() {
void WebView::WebContentsFocused(content::WebContents* web_contents) {
DCHECK(wc_owner_.get());
// The WebView is only the delegate of WebContentses it creates itself.
- OnWebContentsFocused(web_contents_);
+ OnWebContentsFocused(wc_owner_.get());
}
bool WebView::EmbedsFullscreenWidget() const {
@@ -200,19 +248,16 @@ bool WebView::EmbedsFullscreenWidget() const {
////////////////////////////////////////////////////////////////////////////////
// WebView, content::WebContentsObserver implementation:
+void WebView::RenderViewDeleted(content::RenderViewHost* render_view_host) {
+ NotifyMaybeTextInputClientChanged();
+}
+
void WebView::RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
FocusManager* const focus_manager = GetFocusManager();
if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus();
-}
-
-void WebView::WebContentsDestroyed(content::WebContents* web_contents) {
- // We watch for destruction of WebContents that we host but do not own. If we
- // own a WebContents that is being destroyed, we're doing the destroying, so
- // we don't want to recursively tear it down while it's being torn down.
- if (!wc_owner_.get())
- SetWebContents(NULL);
+ NotifyMaybeTextInputClientChanged();
}
void WebView::DidShowFullscreenWidget(int routing_id) {
@@ -225,21 +270,27 @@ void WebView::DidDestroyFullscreenWidget(int routing_id) {
ReattachForFullscreenChange(false);
}
+void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen) {
+ if (embed_fullscreen_widget_mode_enabled_)
+ ReattachForFullscreenChange(entered_fullscreen);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebView, private:
void WebView::AttachWebContents() {
// Prevents attachment if the WebView isn't already in a Widget, or it's
// already attached.
- if (!GetWidget() || !web_contents_)
+ if (!GetWidget() || !web_contents())
return;
const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ?
- web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() :
- web_contents_->GetView()->GetNativeView();
- if (wcv_holder_->native_view() == view_to_attach)
+ web_contents()->GetFullscreenRenderWidgetHostView()->GetNativeView() :
+ web_contents()->GetNativeView();
+ OnBoundsChanged(bounds());
+ if (holder_->native_view() == view_to_attach)
return;
- wcv_holder_->Attach(view_to_attach);
+ holder_->Attach(view_to_attach);
// The view will not be focused automatically when it is attached, so we need
// to pass on focus to it if the FocusManager thinks the view is focused. Note
@@ -248,58 +299,61 @@ void WebView::AttachWebContents() {
if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus();
- WebContentsObserver::Observe(web_contents_);
-
-#if defined(OS_WIN) && defined(USE_AURA)
+#if defined(OS_WIN)
if (!is_embedding_fullscreen_widget_) {
- web_contents_->SetParentNativeViewAccessible(
+ web_contents()->SetParentNativeViewAccessible(
parent()->GetNativeViewAccessible());
}
#endif
}
void WebView::DetachWebContents() {
- if (web_contents_) {
- wcv_holder_->Detach();
+ if (web_contents()) {
+ holder_->Detach();
#if defined(OS_WIN)
- if (!is_embedding_fullscreen_widget_) {
-#if !defined(USE_AURA)
- // TODO(beng): This should either not be necessary, or be done implicitly
- // by NativeViewHostWin on Detach(). As it stands, this is needed so that
- // the of the detached contents knows to tell the renderer it's been
- // hidden.
- //
- // Moving this out of here would also mean we wouldn't be potentially
- // calling member functions on a half-destroyed WebContents.
- ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE);
-#else
- web_contents_->SetParentNativeViewAccessible(NULL);
-#endif
- }
+ if (!is_embedding_fullscreen_widget_)
+ web_contents()->SetParentNativeViewAccessible(NULL);
#endif
}
- WebContentsObserver::Observe(NULL);
}
void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
- DetachWebContents();
- is_embedding_fullscreen_widget_ = enter_fullscreen &&
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
- AttachWebContents();
+ DCHECK(embed_fullscreen_widget_mode_enabled_);
+ const bool web_contents_has_separate_fs_widget =
+ web_contents() && web_contents()->GetFullscreenRenderWidgetHostView();
+ if (is_embedding_fullscreen_widget_ || web_contents_has_separate_fs_widget) {
+ // Shutting down or starting up the embedding of the separate fullscreen
+ // widget. Need to detach and re-attach to a different native view.
+ DetachWebContents();
+ is_embedding_fullscreen_widget_ =
+ enter_fullscreen && web_contents_has_separate_fs_widget;
+ AttachWebContents();
+ } else {
+ // Entering or exiting "non-Flash" fullscreen mode, where the native view is
+ // the same. So, do not change attachment.
+ OnBoundsChanged(bounds());
+ }
+ NotifyMaybeTextInputClientChanged();
+}
+
+void WebView::NotifyMaybeTextInputClientChanged() {
+ // Update the TextInputClient as needed; see GetTextInputClient().
+ FocusManager* const focus_manager = GetFocusManager();
+ if (focus_manager)
+ focus_manager->OnTextInputClientChanged(this);
}
content::WebContents* WebView::CreateWebContents(
- content::BrowserContext* browser_context,
- content::SiteInstance* site_instance) {
+ content::BrowserContext* browser_context) {
content::WebContents* contents = NULL;
if (ViewsDelegate::views_delegate) {
contents = ViewsDelegate::views_delegate->CreateWebContents(
- browser_context, site_instance);
+ browser_context, NULL);
}
if (!contents) {
content::WebContents::CreateParams create_params(
- browser_context, site_instance);
+ browser_context, NULL);
return content::WebContents::Create(create_params);
}