1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/web_contents/web_contents_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/files/file_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/browser/browser_plugin/browser_plugin_guest.h"
12 #include "content/browser/download/drag_download_util.h"
13 #include "content/browser/frame_host/interstitial_page_impl.h"
14 #include "content/browser/frame_host/navigation_entry_impl.h"
15 #include "content/browser/renderer_host/dip_util.h"
16 #include "content/browser/renderer_host/overscroll_controller.h"
17 #include "content/browser/renderer_host/render_view_host_factory.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
21 #include "content/browser/renderer_host/web_input_event_aura.h"
22 #include "content/browser/web_contents/aura/gesture_nav_simple.h"
23 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
24 #include "content/browser/web_contents/touch_editable_impl_aura.h"
25 #include "content/browser/web_contents/web_contents_impl.h"
26 #include "content/public/browser/content_browser_client.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_source.h"
30 #include "content/public/browser/notification_types.h"
31 #include "content/public/browser/overscroll_configuration.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/render_widget_host.h"
34 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/web_contents_delegate.h"
36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/browser/web_contents_view_delegate.h"
38 #include "content/public/browser/web_drag_dest_delegate.h"
39 #include "content/public/common/content_client.h"
40 #include "content/public/common/content_switches.h"
41 #include "content/public/common/drop_data.h"
42 #include "net/base/filename_util.h"
43 #include "third_party/WebKit/public/web/WebInputEvent.h"
44 #include "ui/aura/client/aura_constants.h"
45 #include "ui/aura/client/window_tree_client.h"
46 #include "ui/aura/env.h"
47 #include "ui/aura/window.h"
48 #include "ui/aura/window_observer.h"
49 #include "ui/aura/window_tree_host.h"
50 #include "ui/aura/window_tree_host_observer.h"
51 #include "ui/base/clipboard/clipboard.h"
52 #include "ui/base/clipboard/custom_data_helper.h"
53 #include "ui/base/dragdrop/drag_drop_types.h"
54 #include "ui/base/dragdrop/drag_utils.h"
55 #include "ui/base/dragdrop/drop_target_event.h"
56 #include "ui/base/dragdrop/os_exchange_data.h"
57 #include "ui/base/hit_test.h"
58 #include "ui/compositor/layer.h"
59 #include "ui/events/event.h"
60 #include "ui/events/event_utils.h"
61 #include "ui/gfx/canvas.h"
62 #include "ui/gfx/image/image.h"
63 #include "ui/gfx/image/image_png_rep.h"
64 #include "ui/gfx/image/image_skia.h"
65 #include "ui/gfx/screen.h"
66 #include "ui/wm/public/drag_drop_client.h"
67 #include "ui/wm/public/drag_drop_delegate.h"
70 WebContentsView
* CreateWebContentsView(
71 WebContentsImpl
* web_contents
,
72 WebContentsViewDelegate
* delegate
,
73 RenderViewHostDelegateView
** render_view_host_delegate_view
) {
74 WebContentsViewAura
* rv
= new WebContentsViewAura(web_contents
, delegate
);
75 *render_view_host_delegate_view
= rv
;
81 bool IsScrollEndEffectEnabled() {
82 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
83 switches::kScrollEndEffect
) == "1";
86 RenderWidgetHostViewAura
* ToRenderWidgetHostViewAura(
87 RenderWidgetHostView
* view
) {
88 if (!view
|| RenderViewHostFactory::has_factory())
89 return NULL
; // Can't cast to RenderWidgetHostViewAura in unit tests.
91 RenderViewHost
* rvh
= RenderViewHost::From(view
->GetRenderWidgetHost());
92 WebContentsImpl
* web_contents
= static_cast<WebContentsImpl
*>(
93 rvh
? WebContents::FromRenderViewHost(rvh
) : NULL
);
94 if (BrowserPluginGuest::IsGuest(web_contents
))
96 return static_cast<RenderWidgetHostViewAura
*>(view
);
99 // Listens to all mouse drag events during a drag and drop and sends them to
101 class WebDragSourceAura
: public NotificationObserver
{
103 WebDragSourceAura(aura::Window
* window
, WebContentsImpl
* contents
)
105 contents_(contents
) {
107 NOTIFICATION_WEB_CONTENTS_DISCONNECTED
,
108 Source
<WebContents
>(contents
));
111 ~WebDragSourceAura() override
{}
113 // NotificationObserver:
114 void Observe(int type
,
115 const NotificationSource
& source
,
116 const NotificationDetails
& details
) override
{
117 if (type
!= NOTIFICATION_WEB_CONTENTS_DISCONNECTED
)
120 // Cancel the drag if it is still in progress.
121 aura::client::DragDropClient
* dnd_client
=
122 aura::client::GetDragDropClient(window_
->GetRootWindow());
123 if (dnd_client
&& dnd_client
->IsDragDropInProgress())
124 dnd_client
->DragCancel();
130 aura::Window
* window() const { return window_
; }
133 aura::Window
* window_
;
134 WebContentsImpl
* contents_
;
135 NotificationRegistrar registrar_
;
137 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura
);
140 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
141 // Fill out the OSExchangeData with a file contents, synthesizing a name if
143 void PrepareDragForFileContents(const DropData
& drop_data
,
144 ui::OSExchangeData::Provider
* provider
) {
145 base::FilePath file_name
=
146 base::FilePath::FromUTF16Unsafe(drop_data
.file_description_filename
);
147 // Images without ALT text will only have a file extension so we need to
148 // synthesize one from the provided extension and URL.
149 if (file_name
.BaseName().RemoveExtension().empty()) {
150 const base::FilePath::StringType extension
= file_name
.Extension();
151 // Retrieve the name from the URL.
152 file_name
= net::GenerateFileName(drop_data
.url
, "", "", "", "", "")
153 .ReplaceExtension(extension
);
155 provider
->SetFileContents(file_name
, drop_data
.file_contents
);
160 void PrepareDragForDownload(
161 const DropData
& drop_data
,
162 ui::OSExchangeData::Provider
* provider
,
163 WebContentsImpl
* web_contents
) {
164 const GURL
& page_url
= web_contents
->GetLastCommittedURL();
165 const std::string
& page_encoding
= web_contents
->GetEncoding();
167 // Parse the download metadata.
168 base::string16 mime_type
;
169 base::FilePath file_name
;
171 if (!ParseDownloadMetadata(drop_data
.download_metadata
,
177 // Generate the file name based on both mime type and proposed file name.
178 std::string default_name
=
179 GetContentClient()->browser()->GetDefaultDownloadName();
180 base::FilePath generated_download_file_name
=
181 net::GenerateFileName(download_url
,
184 base::UTF16ToUTF8(file_name
.value()),
185 base::UTF16ToUTF8(mime_type
),
188 // http://crbug.com/332579
189 base::ThreadRestrictions::ScopedAllowIO allow_file_operations
;
191 base::FilePath temp_dir_path
;
192 if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
196 base::FilePath download_path
=
197 temp_dir_path
.Append(generated_download_file_name
);
199 // We cannot know when the target application will be done using the temporary
200 // file, so schedule it to be deleted after rebooting.
201 base::DeleteFileAfterReboot(download_path
);
202 base::DeleteFileAfterReboot(temp_dir_path
);
204 // Provide the data as file (CF_HDROP). A temporary download file with the
205 // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
206 scoped_refptr
<DragDownloadFile
> download_file
=
207 new DragDownloadFile(
211 Referrer(page_url
, drop_data
.referrer_policy
),
214 ui::OSExchangeData::DownloadFileInfo
file_download(base::FilePath(),
215 download_file
.get());
216 provider
->SetDownloadFileInfo(file_download
);
218 #endif // defined(OS_WIN)
220 // Returns the CustomFormat to store file system files.
221 const ui::OSExchangeData::CustomFormat
& GetFileSystemFileCustomFormat() {
222 static const char kFormatString
[] = "chromium/x-file-system-files";
223 CR_DEFINE_STATIC_LOCAL(ui::OSExchangeData::CustomFormat
,
225 (ui::Clipboard::GetFormatType(kFormatString
)));
229 // Writes file system files to the pickle.
230 void WriteFileSystemFilesToPickle(
231 const std::vector
<DropData::FileSystemFileInfo
>& file_system_files
,
233 pickle
->WriteSizeT(file_system_files
.size());
234 for (size_t i
= 0; i
< file_system_files
.size(); ++i
) {
235 pickle
->WriteString(file_system_files
[i
].url
.spec());
236 pickle
->WriteInt64(file_system_files
[i
].size
);
240 // Reads file system files from the pickle.
241 bool ReadFileSystemFilesFromPickle(
242 const Pickle
& pickle
,
243 std::vector
<DropData::FileSystemFileInfo
>* file_system_files
) {
244 PickleIterator
iter(pickle
);
246 size_t num_files
= 0;
247 if (!iter
.ReadSizeT(&num_files
))
249 file_system_files
->resize(num_files
);
251 for (size_t i
= 0; i
< num_files
; ++i
) {
252 std::string url_string
;
254 if (!iter
.ReadString(&url_string
) || !iter
.ReadInt64(&size
))
257 GURL
url(url_string
);
261 (*file_system_files
)[i
].url
= url
;
262 (*file_system_files
)[i
].size
= size
;
267 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
268 void PrepareDragData(const DropData
& drop_data
,
269 ui::OSExchangeData::Provider
* provider
,
270 WebContentsImpl
* web_contents
) {
271 provider
->MarkOriginatedFromRenderer();
273 // Put download before file contents to prefer the download of a image over
274 // its thumbnail link.
275 if (!drop_data
.download_metadata
.empty())
276 PrepareDragForDownload(drop_data
, provider
, web_contents
);
278 #if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
279 // We set the file contents before the URL because the URL also sets file
280 // contents (to a .URL shortcut). We want to prefer file content data over
281 // a shortcut so we add it first.
282 if (!drop_data
.file_contents
.empty())
283 PrepareDragForFileContents(drop_data
, provider
);
285 // Call SetString() before SetURL() when we actually have a custom string.
286 // SetURL() will itself do SetString() when a string hasn't been set yet,
287 // but we want to prefer drop_data.text.string() over the URL string if it
289 if (!drop_data
.text
.string().empty())
290 provider
->SetString(drop_data
.text
.string());
291 if (drop_data
.url
.is_valid())
292 provider
->SetURL(drop_data
.url
, drop_data
.url_title
);
293 if (!drop_data
.html
.string().empty())
294 provider
->SetHtml(drop_data
.html
.string(), drop_data
.html_base_url
);
295 if (!drop_data
.filenames
.empty())
296 provider
->SetFilenames(drop_data
.filenames
);
297 if (!drop_data
.file_system_files
.empty()) {
299 WriteFileSystemFilesToPickle(drop_data
.file_system_files
, &pickle
);
300 provider
->SetPickledData(GetFileSystemFileCustomFormat(), pickle
);
302 if (!drop_data
.custom_data
.empty()) {
304 ui::WriteCustomDataToPickle(drop_data
.custom_data
, &pickle
);
305 provider
->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
310 // Utility to fill a DropData object from ui::OSExchangeData.
311 void PrepareDropData(DropData
* drop_data
, const ui::OSExchangeData
& data
) {
312 drop_data
->did_originate_from_renderer
= data
.DidOriginateFromRenderer();
314 base::string16 plain_text
;
315 data
.GetString(&plain_text
);
316 if (!plain_text
.empty())
317 drop_data
->text
= base::NullableString16(plain_text
, false);
320 base::string16 url_title
;
322 ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES
, &url
, &url_title
);
323 if (url
.is_valid()) {
324 drop_data
->url
= url
;
325 drop_data
->url_title
= url_title
;
330 data
.GetHtml(&html
, &html_base_url
);
332 drop_data
->html
= base::NullableString16(html
, false);
333 if (html_base_url
.is_valid())
334 drop_data
->html_base_url
= html_base_url
;
336 data
.GetFilenames(&drop_data
->filenames
);
339 std::vector
<DropData::FileSystemFileInfo
> file_system_files
;
340 if (data
.GetPickledData(GetFileSystemFileCustomFormat(), &pickle
) &&
341 ReadFileSystemFilesFromPickle(pickle
, &file_system_files
))
342 drop_data
->file_system_files
= file_system_files
;
344 if (data
.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle
))
345 ui::ReadCustomDataIntoMap(
346 pickle
.data(), pickle
.size(), &drop_data
->custom_data
);
349 // Utilities to convert between blink::WebDragOperationsMask and
350 // ui::DragDropTypes.
351 int ConvertFromWeb(blink::WebDragOperationsMask ops
) {
352 int drag_op
= ui::DragDropTypes::DRAG_NONE
;
353 if (ops
& blink::WebDragOperationCopy
)
354 drag_op
|= ui::DragDropTypes::DRAG_COPY
;
355 if (ops
& blink::WebDragOperationMove
)
356 drag_op
|= ui::DragDropTypes::DRAG_MOVE
;
357 if (ops
& blink::WebDragOperationLink
)
358 drag_op
|= ui::DragDropTypes::DRAG_LINK
;
362 blink::WebDragOperationsMask
ConvertToWeb(int drag_op
) {
363 int web_drag_op
= blink::WebDragOperationNone
;
364 if (drag_op
& ui::DragDropTypes::DRAG_COPY
)
365 web_drag_op
|= blink::WebDragOperationCopy
;
366 if (drag_op
& ui::DragDropTypes::DRAG_MOVE
)
367 web_drag_op
|= blink::WebDragOperationMove
;
368 if (drag_op
& ui::DragDropTypes::DRAG_LINK
)
369 web_drag_op
|= blink::WebDragOperationLink
;
370 return (blink::WebDragOperationsMask
) web_drag_op
;
373 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags
) {
374 int web_input_event_modifiers
= 0;
375 if (aura_event_flags
& ui::EF_SHIFT_DOWN
)
376 web_input_event_modifiers
|= blink::WebInputEvent::ShiftKey
;
377 if (aura_event_flags
& ui::EF_CONTROL_DOWN
)
378 web_input_event_modifiers
|= blink::WebInputEvent::ControlKey
;
379 if (aura_event_flags
& ui::EF_ALT_DOWN
)
380 web_input_event_modifiers
|= blink::WebInputEvent::AltKey
;
381 if (aura_event_flags
& ui::EF_COMMAND_DOWN
)
382 web_input_event_modifiers
|= blink::WebInputEvent::MetaKey
;
383 if (aura_event_flags
& ui::EF_LEFT_MOUSE_BUTTON
)
384 web_input_event_modifiers
|= blink::WebInputEvent::LeftButtonDown
;
385 if (aura_event_flags
& ui::EF_MIDDLE_MOUSE_BUTTON
)
386 web_input_event_modifiers
|= blink::WebInputEvent::MiddleButtonDown
;
387 if (aura_event_flags
& ui::EF_RIGHT_MOUSE_BUTTON
)
388 web_input_event_modifiers
|= blink::WebInputEvent::RightButtonDown
;
389 return web_input_event_modifiers
;
394 class WebContentsViewAura::WindowObserver
395 : public aura::WindowObserver
, public aura::WindowTreeHostObserver
{
397 explicit WindowObserver(WebContentsViewAura
* view
)
400 view_
->window_
->AddObserver(this);
403 if (view_
->window_
->GetRootWindow())
404 view_
->window_
->GetRootWindow()->AddObserver(this);
408 ~WindowObserver() override
{
409 view_
->window_
->RemoveObserver(this);
410 if (view_
->window_
->GetHost())
411 view_
->window_
->GetHost()->RemoveObserver(this);
413 host_window_
->RemoveObserver(this);
416 const aura::Window::Windows
& children
= host_window_
->children();
417 for (size_t i
= 0; i
< children
.size(); ++i
)
418 children
[i
]->RemoveObserver(this);
421 aura::Window
* root_window
= view_
->window_
->GetRootWindow();
423 root_window
->RemoveObserver(this);
424 const aura::Window::Windows
& root_children
= root_window
->children();
425 for (size_t i
= 0; i
< root_children
.size(); ++i
)
426 root_children
[i
]->RemoveObserver(this);
432 // Constrained windows are added as children of the parent's parent's view
433 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
434 // so that it can update the plugins' cutout rects accordingly.
435 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
436 // going to be deprecated in a year, this is ok for now. The test for this is
437 // PrintPreviewTest.WindowedNPAPIPluginHidden.
438 virtual void OnWindowAdded(aura::Window
* new_window
) override
{
439 if (!new_window
->Contains(view_
->window_
.get())) {
440 // Skip the case when the parent moves to the root window.
441 if (new_window
!= host_window_
) {
442 // Observe sibling windows of the WebContents, or children of the root
444 if (new_window
->parent() == host_window_
||
445 new_window
->parent() == view_
->window_
->GetRootWindow()) {
446 new_window
->AddObserver(this);
451 if (new_window
->parent() == host_window_
) {
452 UpdateConstrainedWindows(NULL
);
456 virtual void OnWillRemoveWindow(aura::Window
* window
) override
{
457 if (window
== view_
->window_
)
460 window
->RemoveObserver(this);
461 UpdateConstrainedWindows(window
);
464 virtual void OnWindowVisibilityChanged(aura::Window
* window
,
465 bool visible
) override
{
466 if (window
== view_
->window_
||
467 window
->parent() == host_window_
||
468 window
->parent() == view_
->window_
->GetRootWindow()) {
469 UpdateConstrainedWindows(NULL
);
474 void OnWindowParentChanged(aura::Window
* window
,
475 aura::Window
* parent
) override
{
476 if (window
!= view_
->window_
)
479 aura::Window
* host_window
=
480 window
->GetProperty(aura::client::kHostWindowKey
);
482 host_window
= parent
;
485 host_window_
->RemoveObserver(this);
489 const aura::Window::Windows
& children
= host_window_
->children();
490 for (size_t i
= 0; i
< children
.size(); ++i
)
491 children
[i
]->RemoveObserver(this);
492 RenderWidgetHostViewAura
* rwhv
= ToRenderWidgetHostViewAura(
493 view_
->web_contents_
->GetRenderWidgetHostView());
495 rwhv
->UpdateConstrainedWindowRects(std::vector
<gfx::Rect
>());
498 // When we get parented to the root window, the code below will watch the
499 // host window, aka root window. Since we already watch the root window on
500 // Windows, unregister first so that the debug check doesn't fire.
501 if (host_window
&& host_window
== window
->GetRootWindow())
502 host_window
->RemoveObserver(this);
504 // We need to undo the above if we were parented to the root window and then
505 // got parented to another window. At that point, the code before the ifdef
506 // would have stopped watching the root window.
507 if (window
->GetRootWindow() &&
508 host_window
!= window
->GetRootWindow() &&
509 !window
->GetRootWindow()->HasObserver(this)) {
510 window
->GetRootWindow()->AddObserver(this);
514 host_window_
= host_window
;
516 host_window
->AddObserver(this);
518 if (host_window
!= window
->GetRootWindow()) {
519 const aura::Window::Windows
& children
= host_window
->children();
520 for (size_t i
= 0; i
< children
.size(); ++i
) {
521 if (!children
[i
]->Contains(view_
->window_
.get()))
522 children
[i
]->AddObserver(this);
529 void OnWindowBoundsChanged(aura::Window
* window
,
530 const gfx::Rect
& old_bounds
,
531 const gfx::Rect
& new_bounds
) override
{
532 if (window
== host_window_
|| window
== view_
->window_
) {
534 if (view_
->touch_editable_
)
535 view_
->touch_editable_
->UpdateEditingController();
538 UpdateConstrainedWindows(NULL
);
543 void OnWindowDestroying(aura::Window
* window
) override
{
544 if (window
== host_window_
) {
545 host_window_
->RemoveObserver(this);
550 void OnWindowAddedToRootWindow(aura::Window
* window
) override
{
551 if (window
== view_
->window_
) {
552 window
->GetHost()->AddObserver(this);
554 if (!window
->GetRootWindow()->HasObserver(this))
555 window
->GetRootWindow()->AddObserver(this);
560 void OnWindowRemovingFromRootWindow(aura::Window
* window
,
561 aura::Window
* new_root
) override
{
562 if (window
== view_
->window_
) {
563 window
->GetHost()->RemoveObserver(this);
565 window
->GetRootWindow()->RemoveObserver(this);
567 const aura::Window::Windows
& root_children
=
568 window
->GetRootWindow()->children();
569 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
570 if (root_children
[i
] != view_
->window_
&&
571 root_children
[i
] != host_window_
) {
572 root_children
[i
]->RemoveObserver(this);
579 // Overridden WindowTreeHostObserver:
580 void OnHostMoved(const aura::WindowTreeHost
* host
,
581 const gfx::Point
& new_origin
) override
{
583 "WebContentsViewAura::WindowObserver::OnHostMoved",
584 "new_origin", new_origin
.ToString());
586 // This is for the desktop case (i.e. Aura desktop).
591 void SendScreenRects() {
592 RenderWidgetHostImpl::From(view_
->web_contents_
->GetRenderViewHost())->
597 void UpdateConstrainedWindows(aura::Window
* exclude
) {
598 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
599 view_
->web_contents_
->GetRenderWidgetHostView());
603 std::vector
<gfx::Rect
> constrained_windows
;
605 const aura::Window::Windows
& children
= host_window_
->children();
606 for (size_t i
= 0; i
< children
.size(); ++i
) {
607 if (!children
[i
]->Contains(view_
->window_
.get()) &&
608 children
[i
] != exclude
&&
609 children
[i
]->IsVisible()) {
610 constrained_windows
.push_back(children
[i
]->GetBoundsInRootWindow());
615 aura::Window
* root_window
= view_
->window_
->GetRootWindow();
616 const aura::Window::Windows
& root_children
= root_window
->children();
618 for (size_t i
= 0; i
< root_children
.size(); ++i
) {
619 if (root_children
[i
]->IsVisible() &&
620 !root_children
[i
]->Contains(view_
->window_
.get())) {
621 constrained_windows
.push_back(
622 root_children
[i
]->GetBoundsInRootWindow());
627 view
->UpdateConstrainedWindowRects(constrained_windows
);
631 WebContentsViewAura
* view_
;
633 // The parent window that hosts the constrained windows. We cache the old host
634 // view so that we can unregister when it's not the parent anymore.
635 aura::Window
* host_window_
;
637 DISALLOW_COPY_AND_ASSIGN(WindowObserver
);
640 ////////////////////////////////////////////////////////////////////////////////
641 // WebContentsViewAura, public:
643 WebContentsViewAura::WebContentsViewAura(WebContentsImpl
* web_contents
,
644 WebContentsViewDelegate
* delegate
)
645 : web_contents_(web_contents
),
647 current_drag_op_(blink::WebDragOperationNone
),
648 drag_dest_delegate_(NULL
),
649 current_rvh_for_drag_(NULL
),
650 current_overscroll_gesture_(OVERSCROLL_NONE
),
651 completed_overscroll_gesture_(OVERSCROLL_NONE
),
652 navigation_overlay_(nullptr),
653 touch_editable_(TouchEditableImplAura::Create()),
654 is_or_was_visible_(false) {
657 ////////////////////////////////////////////////////////////////////////////////
658 // WebContentsViewAura, private:
660 WebContentsViewAura::~WebContentsViewAura() {
664 window_observer_
.reset();
665 window_
->RemoveObserver(this);
667 // Window needs a valid delegate during its destructor, so we explicitly
672 void WebContentsViewAura::SetTouchEditableForTest(
673 TouchEditableImplAura
* touch_editable
) {
674 touch_editable_
.reset(touch_editable
);
675 AttachTouchEditableToRenderView();
678 void WebContentsViewAura::SizeChangedCommon(const gfx::Size
& size
) {
679 if (web_contents_
->GetInterstitialPage())
680 web_contents_
->GetInterstitialPage()->SetSize(size
);
681 RenderWidgetHostView
* rwhv
=
682 web_contents_
->GetRenderWidgetHostView();
687 void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops
) {
688 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
689 gfx::Point screen_loc
=
690 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
691 gfx::Point client_loc
= screen_loc
;
692 RenderViewHost
* rvh
= web_contents_
->GetRenderViewHost();
693 aura::Window
* window
= rvh
->GetView()->GetNativeView();
694 aura::Window::ConvertPointToTarget(root_window
, window
, &client_loc
);
697 web_contents_
->DragSourceEndedAt(client_loc
.x(), client_loc
.y(),
698 screen_loc
.x(), screen_loc
.y(), ops
);
701 void WebContentsViewAura::InstallOverscrollControllerDelegate(
702 RenderWidgetHostViewAura
* view
) {
703 const std::string value
= base::CommandLine::ForCurrentProcess()->
704 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
);
706 navigation_overlay_
.reset();
710 navigation_overlay_
.reset();
711 if (!gesture_nav_simple_
)
712 gesture_nav_simple_
.reset(new GestureNavSimple(web_contents_
));
713 view
->overscroll_controller()->set_delegate(gesture_nav_simple_
.get());
716 view
->overscroll_controller()->set_delegate(this);
717 if (!navigation_overlay_
) {
718 navigation_overlay_
.reset(
719 new OverscrollNavigationOverlay(web_contents_
, window_
.get()));
723 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode
) {
724 if (!web_contents_
->GetRenderWidgetHostView())
726 navigation_overlay_
->relay_delegate()->OnOverscrollComplete(mode
);
728 touch_editable_
->OverscrollCompleted();
731 void WebContentsViewAura::AttachTouchEditableToRenderView() {
732 if (!touch_editable_
)
734 RenderWidgetHostViewAura
* rwhva
= ToRenderWidgetHostViewAura(
735 web_contents_
->GetRenderWidgetHostView());
736 touch_editable_
->AttachToView(rwhva
);
739 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
741 if (web_contents_
->GetDelegate() && IsScrollEndEffectEnabled())
742 web_contents_
->GetDelegate()->OverscrollUpdate(delta_y
);
745 ////////////////////////////////////////////////////////////////////////////////
746 // WebContentsViewAura, WebContentsView implementation:
748 gfx::NativeView
WebContentsViewAura::GetNativeView() const {
749 return window_
.get();
752 gfx::NativeView
WebContentsViewAura::GetContentNativeView() const {
753 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
754 return rwhv
? rwhv
->GetNativeView() : NULL
;
757 gfx::NativeWindow
WebContentsViewAura::GetTopLevelNativeWindow() const {
758 gfx::NativeWindow window
= window_
->GetToplevelWindow();
759 return window
? window
: delegate_
->GetNativeWindow();
762 void WebContentsViewAura::GetContainerBounds(gfx::Rect
*out
) const {
763 *out
= window_
->GetBoundsInScreen();
766 void WebContentsViewAura::SizeContents(const gfx::Size
& size
) {
767 gfx::Rect bounds
= window_
->bounds();
768 if (bounds
.size() != size
) {
769 bounds
.set_size(size
);
770 window_
->SetBounds(bounds
);
772 // Our size matches what we want but the renderers size may not match.
773 // Pretend we were resized so that the renderers size is updated too.
774 SizeChangedCommon(size
);
778 void WebContentsViewAura::Focus() {
779 if (web_contents_
->GetInterstitialPage()) {
780 web_contents_
->GetInterstitialPage()->Focus();
784 if (delegate_
.get() && delegate_
->Focus())
787 RenderWidgetHostView
* rwhv
=
788 web_contents_
->GetFullscreenRenderWidgetHostView();
790 rwhv
= web_contents_
->GetRenderWidgetHostView();
795 void WebContentsViewAura::SetInitialFocus() {
796 if (web_contents_
->FocusLocationBarByDefault())
797 web_contents_
->SetFocusToLocationBar(false);
802 void WebContentsViewAura::StoreFocus() {
804 delegate_
->StoreFocus();
807 void WebContentsViewAura::RestoreFocus() {
809 delegate_
->RestoreFocus();
812 DropData
* WebContentsViewAura::GetDropData() const {
813 return current_drop_data_
.get();
816 gfx::Rect
WebContentsViewAura::GetViewBounds() const {
817 return window_
->GetBoundsInScreen();
820 ////////////////////////////////////////////////////////////////////////////////
821 // WebContentsViewAura, WebContentsView implementation:
823 void WebContentsViewAura::CreateView(
824 const gfx::Size
& initial_size
, gfx::NativeView context
) {
825 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
826 // if the bookmark bar is not shown and you create a new tab). The right
827 // value is set shortly after this, so its safe to ignore.
829 aura::Env::CreateInstance(true);
830 window_
.reset(new aura::Window(this));
831 window_
->set_owned_by_parent(false);
832 window_
->SetType(ui::wm::WINDOW_TYPE_CONTROL
);
833 window_
->SetTransparent(false);
834 window_
->Init(ui::LAYER_NOT_DRAWN
);
835 window_
->AddObserver(this);
836 aura::Window
* root_window
= context
? context
->GetRootWindow() : NULL
;
838 // There are places where there is no context currently because object
839 // hierarchies are built before they're attached to a Widget. (See
840 // views::WebView as an example; GetWidget() returns NULL at the point
841 // where we are created.)
843 // It should be OK to not set a default parent since such users will
844 // explicitly add this WebContentsViewAura to their tree after they create
847 aura::client::ParentWindowWithContext(
848 window_
.get(), root_window
, root_window
->GetBoundsInScreen());
851 window_
->layer()->SetMasksToBounds(true);
852 window_
->SetName("WebContentsViewAura");
854 // WindowObserver is not interesting and is problematic for Browser Plugin
856 // The use cases for WindowObserver do not apply to Browser Plugins:
857 // 1) guests do not support NPAPI plugins.
858 // 2) guests' window bounds are supposed to come from its embedder.
859 if (!BrowserPluginGuest::IsGuest(web_contents_
))
860 window_observer_
.reset(new WindowObserver(this));
862 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
863 // Hence, we save a reference to it locally. Similar model is used on other
864 // platforms as well.
866 drag_dest_delegate_
= delegate_
->GetDragDestDelegate();
869 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForWidget(
870 RenderWidgetHost
* render_widget_host
, bool is_guest_view_hack
) {
871 if (render_widget_host
->GetView()) {
872 // During testing, the view will already be set up in most cases to the
873 // test view, so we don't want to clobber it with a real one. To verify that
874 // this actually is happening (and somebody isn't accidentally creating the
875 // view twice), we check for the RVH Factory, which will be set when we're
876 // making special ones (which go along with the special views).
877 DCHECK(RenderViewHostFactory::has_factory());
878 return static_cast<RenderWidgetHostViewBase
*>(
879 render_widget_host
->GetView());
882 RenderWidgetHostViewAura
* view
=
883 new RenderWidgetHostViewAura(render_widget_host
, is_guest_view_hack
);
884 view
->InitAsChild(NULL
);
885 GetNativeView()->AddChild(view
->GetNativeView());
887 RenderWidgetHostImpl
* host_impl
=
888 RenderWidgetHostImpl::From(render_widget_host
);
890 if (!host_impl
->is_hidden())
893 // We listen to drag drop events in the newly created view's window.
894 aura::client::SetDragDropDelegate(view
->GetNativeView(), this);
896 if (view
->overscroll_controller() &&
897 (!web_contents_
->GetDelegate() ||
898 web_contents_
->GetDelegate()->CanOverscrollContent())) {
899 InstallOverscrollControllerDelegate(view
);
902 AttachTouchEditableToRenderView();
906 RenderWidgetHostViewBase
* WebContentsViewAura::CreateViewForPopupWidget(
907 RenderWidgetHost
* render_widget_host
) {
908 return new RenderWidgetHostViewAura(render_widget_host
, false);
911 void WebContentsViewAura::SetPageTitle(const base::string16
& title
) {
912 window_
->SetTitle(title
);
915 void WebContentsViewAura::RenderViewCreated(RenderViewHost
* host
) {
918 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost
* host
) {
919 AttachTouchEditableToRenderView();
922 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled
) {
923 RenderWidgetHostViewAura
* view
=
924 ToRenderWidgetHostViewAura(web_contents_
->GetRenderWidgetHostView());
926 view
->SetOverscrollControllerEnabled(enabled
);
928 InstallOverscrollControllerDelegate(view
);
932 navigation_overlay_
.reset();
933 } else if (!navigation_overlay_
) {
934 navigation_overlay_
.reset(
935 new OverscrollNavigationOverlay(web_contents_
, window_
.get()));
939 ////////////////////////////////////////////////////////////////////////////////
940 // WebContentsViewAura, RenderViewHostDelegateView implementation:
942 void WebContentsViewAura::ShowContextMenu(RenderFrameHost
* render_frame_host
,
943 const ContextMenuParams
& params
) {
944 if (touch_editable_
) {
945 touch_editable_
->EndTouchEditing(false);
948 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
949 web_contents_
->GetRenderWidgetHostView());
951 view
->OnShowContextMenu();
953 delegate_
->ShowContextMenu(render_frame_host
, params
);
954 // WARNING: we may have been deleted during the call to ShowContextMenu().
958 void WebContentsViewAura::StartDragging(
959 const DropData
& drop_data
,
960 blink::WebDragOperationsMask operations
,
961 const gfx::ImageSkia
& image
,
962 const gfx::Vector2d
& image_offset
,
963 const DragEventSourceInfo
& event_info
) {
964 aura::Window
* root_window
= GetNativeView()->GetRootWindow();
965 if (!aura::client::GetDragDropClient(root_window
)) {
966 web_contents_
->SystemDragEnded();
971 touch_editable_
->EndTouchEditing(false);
973 ui::OSExchangeData::Provider
* provider
= ui::OSExchangeData::CreateProvider();
974 PrepareDragData(drop_data
, provider
, web_contents_
);
976 ui::OSExchangeData
data(provider
); // takes ownership of |provider|.
979 drag_utils::SetDragImageOnDataObject(image
, image_offset
, &data
);
981 scoped_ptr
<WebDragSourceAura
> drag_source(
982 new WebDragSourceAura(GetNativeView(), web_contents_
));
984 // We need to enable recursive tasks on the message loop so we can get
985 // updates while in the system DoDragDrop loop.
988 gfx::NativeView content_native_view
= GetContentNativeView();
989 base::MessageLoop::ScopedNestableTaskAllower
allow(
990 base::MessageLoop::current());
991 result_op
= aura::client::GetDragDropClient(root_window
)
992 ->StartDragAndDrop(data
,
995 event_info
.event_location
,
996 ConvertFromWeb(operations
),
997 event_info
.event_source
);
1000 // Bail out immediately if the contents view window is gone. Note that it is
1001 // not safe to access any class members in this case since |this| may already
1002 // be destroyed. The local variable |drag_source| will still be valid though,
1003 // so we can use it to determine if the window is gone.
1004 if (!drag_source
->window()) {
1005 // Note that in this case, we don't need to call SystemDragEnded() since the
1006 // renderer is going away.
1010 EndDrag(ConvertToWeb(result_op
));
1011 web_contents_
->SystemDragEnded();
1014 void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation
) {
1015 current_drag_op_
= operation
;
1018 void WebContentsViewAura::GotFocus() {
1019 web_contents_
->NotifyWebContentsFocused();
1022 void WebContentsViewAura::TakeFocus(bool reverse
) {
1023 if (web_contents_
->GetDelegate() &&
1024 !web_contents_
->GetDelegate()->TakeFocus(web_contents_
, reverse
) &&
1026 delegate_
->TakeFocus(reverse
);
1030 void WebContentsViewAura::ShowDisambiguationPopup(
1031 const gfx::Rect
& target_rect
,
1032 const SkBitmap
& zoomed_bitmap
,
1033 const base::Callback
<void(ui::GestureEvent
*)>& gesture_cb
,
1034 const base::Callback
<void(ui::MouseEvent
*)>& mouse_cb
) {
1036 delegate_
->ShowDisambiguationPopup(target_rect
, zoomed_bitmap
,
1037 window_
.get(), gesture_cb
, mouse_cb
);
1041 void WebContentsViewAura::HideDisambiguationPopup() {
1043 delegate_
->HideDisambiguationPopup();
1046 ////////////////////////////////////////////////////////////////////////////////
1047 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1049 gfx::Rect
WebContentsViewAura::GetVisibleBounds() const {
1050 RenderWidgetHostView
* rwhv
= web_contents_
->GetRenderWidgetHostView();
1051 if (!rwhv
|| !rwhv
->IsShowing())
1054 return rwhv
->GetViewBounds();
1057 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x
, float delta_y
) {
1058 if (current_overscroll_gesture_
== OVERSCROLL_NONE
)
1061 if (current_overscroll_gesture_
== OVERSCROLL_NORTH
||
1062 current_overscroll_gesture_
== OVERSCROLL_SOUTH
) {
1063 OverscrollUpdateForWebContentsDelegate(delta_y
);
1064 return delta_y
!= 0;
1066 return navigation_overlay_
->relay_delegate()->OnOverscrollUpdate(delta_x
,
1070 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode
) {
1071 if (web_contents_
->GetDelegate() &&
1072 IsScrollEndEffectEnabled() &&
1073 (mode
== OVERSCROLL_NORTH
|| mode
== OVERSCROLL_SOUTH
)) {
1074 web_contents_
->GetDelegate()->OverscrollComplete();
1076 CompleteOverscrollNavigation(mode
);
1079 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode
,
1080 OverscrollMode new_mode
) {
1081 if (old_mode
== OVERSCROLL_NORTH
|| old_mode
== OVERSCROLL_SOUTH
)
1082 OverscrollUpdateForWebContentsDelegate(0);
1084 if (touch_editable_
) {
1085 if (new_mode
== OVERSCROLL_NONE
)
1086 touch_editable_
->OverscrollCompleted();
1088 touch_editable_
->OverscrollStarted();
1091 current_overscroll_gesture_
= new_mode
;
1092 navigation_overlay_
->relay_delegate()->OnOverscrollModeChange(old_mode
,
1094 completed_overscroll_gesture_
= OVERSCROLL_NONE
;
1097 ////////////////////////////////////////////////////////////////////////////////
1098 // WebContentsViewAura, aura::WindowDelegate implementation:
1100 gfx::Size
WebContentsViewAura::GetMinimumSize() const {
1104 gfx::Size
WebContentsViewAura::GetMaximumSize() const {
1108 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect
& old_bounds
,
1109 const gfx::Rect
& new_bounds
) {
1110 SizeChangedCommon(new_bounds
.size());
1112 delegate_
->SizeChanged(new_bounds
.size());
1114 // Constrained web dialogs, need to be kept centered over our content area.
1115 for (size_t i
= 0; i
< window_
->children().size(); i
++) {
1116 if (window_
->children()[i
]->GetProperty(
1117 aura::client::kConstrainedWindowKey
)) {
1118 gfx::Rect bounds
= window_
->children()[i
]->bounds();
1120 gfx::Point((new_bounds
.width() - bounds
.width()) / 2,
1121 (new_bounds
.height() - bounds
.height()) / 2));
1122 window_
->children()[i
]->SetBounds(bounds
);
1127 ui::TextInputClient
* WebContentsViewAura::GetFocusedTextInputClient() {
1131 gfx::NativeCursor
WebContentsViewAura::GetCursor(const gfx::Point
& point
) {
1132 return gfx::kNullCursor
;
1135 int WebContentsViewAura::GetNonClientComponent(const gfx::Point
& point
) const {
1139 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1140 aura::Window
* child
,
1141 const gfx::Point
& location
) {
1145 bool WebContentsViewAura::CanFocus() {
1146 // Do not take the focus if the render widget host view aura is gone or
1147 // is in the process of shutting down because neither the view window nor
1148 // this window can handle key events.
1149 RenderWidgetHostViewAura
* view
= ToRenderWidgetHostViewAura(
1150 web_contents_
->GetRenderWidgetHostView());
1151 if (view
!= NULL
&& !view
->IsClosing())
1157 void WebContentsViewAura::OnCaptureLost() {
1160 void WebContentsViewAura::OnPaint(const ui::PaintContext
& context
) {
1163 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1164 float device_scale_factor
) {
1167 void WebContentsViewAura::OnWindowDestroying(aura::Window
* window
) {
1168 // This means the destructor is going to be called soon. If there is an
1169 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1170 // then destroying it in the WebContentsViewAura destructor can trigger other
1171 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1172 // destroy the overscroll window here.
1173 navigation_overlay_
.reset();
1176 void WebContentsViewAura::OnWindowDestroyed(aura::Window
* window
) {
1179 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible
) {
1182 bool WebContentsViewAura::HasHitTestMask() const {
1186 void WebContentsViewAura::GetHitTestMask(gfx::Path
* mask
) const {
1189 ////////////////////////////////////////////////////////////////////////////////
1190 // WebContentsViewAura, ui::EventHandler implementation:
1192 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent
* event
) {
1195 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent
* event
) {
1196 if (!web_contents_
->GetDelegate())
1199 switch (event
->type()) {
1200 case ui::ET_MOUSE_PRESSED
:
1201 web_contents_
->GetDelegate()->ActivateContents(web_contents_
);
1203 case ui::ET_MOUSE_MOVED
:
1204 case ui::ET_MOUSE_EXITED
:
1205 web_contents_
->GetDelegate()->ContentsMouseEvent(
1207 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1208 event
->type() == ui::ET_MOUSE_MOVED
);
1215 ////////////////////////////////////////////////////////////////////////////////
1216 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1218 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent
& event
) {
1219 current_rvh_for_drag_
= web_contents_
->GetRenderViewHost();
1220 current_drop_data_
.reset(new DropData());
1222 PrepareDropData(current_drop_data_
.get(), event
.data());
1223 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1225 // Give the delegate an opportunity to cancel the drag.
1226 if (web_contents_
->GetDelegate() &&
1227 !web_contents_
->GetDelegate()->CanDragEnter(
1228 web_contents_
, *current_drop_data_
.get(), op
)) {
1229 current_drop_data_
.reset(NULL
);
1233 if (drag_dest_delegate_
)
1234 drag_dest_delegate_
->DragInitialize(web_contents_
);
1236 gfx::Point screen_pt
=
1237 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1238 web_contents_
->GetRenderViewHost()->DragTargetDragEnter(
1239 *current_drop_data_
.get(), event
.location(), screen_pt
, op
,
1240 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1242 if (drag_dest_delegate_
) {
1243 drag_dest_delegate_
->OnReceiveDragData(event
.data());
1244 drag_dest_delegate_
->OnDragEnter();
1248 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent
& event
) {
1249 DCHECK(current_rvh_for_drag_
);
1250 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1251 OnDragEntered(event
);
1253 if (!current_drop_data_
)
1254 return ui::DragDropTypes::DRAG_NONE
;
1256 blink::WebDragOperationsMask op
= ConvertToWeb(event
.source_operations());
1257 gfx::Point screen_pt
=
1258 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1259 web_contents_
->GetRenderViewHost()->DragTargetDragOver(
1260 event
.location(), screen_pt
, op
,
1261 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1263 if (drag_dest_delegate_
)
1264 drag_dest_delegate_
->OnDragOver();
1266 return ConvertFromWeb(current_drag_op_
);
1269 void WebContentsViewAura::OnDragExited() {
1270 DCHECK(current_rvh_for_drag_
);
1271 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1274 if (!current_drop_data_
)
1277 web_contents_
->GetRenderViewHost()->DragTargetDragLeave();
1278 if (drag_dest_delegate_
)
1279 drag_dest_delegate_
->OnDragLeave();
1281 current_drop_data_
.reset();
1284 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent
& event
) {
1285 DCHECK(current_rvh_for_drag_
);
1286 if (current_rvh_for_drag_
!= web_contents_
->GetRenderViewHost())
1287 OnDragEntered(event
);
1289 if (!current_drop_data_
)
1290 return ui::DragDropTypes::DRAG_NONE
;
1292 web_contents_
->GetRenderViewHost()->DragTargetDrop(
1294 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1295 ConvertAuraEventFlagsToWebInputEventModifiers(event
.flags()));
1296 if (drag_dest_delegate_
)
1297 drag_dest_delegate_
->OnDrop();
1298 current_drop_data_
.reset();
1299 return ConvertFromWeb(current_drag_op_
);
1302 void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window
* window
,
1304 // Ignore any visibility changes in the hierarchy below.
1305 if (window
!= window_
.get() && window_
->Contains(window
))
1308 UpdateWebContentsVisibility(visible
);
1311 void WebContentsViewAura::UpdateWebContentsVisibility(bool visible
) {
1312 if (!is_or_was_visible_
) {
1313 // We should not hide the web contents before it was shown the first time,
1314 // since resources would immediately be destroyed and only re-created after
1315 // content got loaded. In this state the window content is undefined and can
1317 // However - the page load mechanism requires an activation call through a
1318 // visibility call to (re)load.
1320 is_or_was_visible_
= true;
1321 web_contents_
->WasShown();
1326 if (!web_contents_
->should_normally_be_visible())
1327 web_contents_
->WasShown();
1329 if (web_contents_
->should_normally_be_visible())
1330 web_contents_
->WasHidden();
1334 } // namespace content