#include "content/browser/web_contents/web_contents_view_aura.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "components/viz/common/features.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/download/drag_download_util.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "net/base/filename_util.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/drag/drag.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/layer.h"
#include "ui/display/screen.h"
#include "ui/events/blink/web_input_event.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/touch_selection/touch_selection_controller.h"
namespace content {
std::unique_ptr<WebContentsView> CreateWebContentsView(
WebContentsImpl* web_contents,
std::unique_ptr<WebContentsViewDelegate> delegate,
raw_ptr<RenderViewHostDelegateView>* render_view_host_delegate_view) { … }
class ScopedAllowBlockingForViewAura : public base::ScopedAllowBlocking { … };
namespace {
DragOperation;
WebContentsViewAura::RenderWidgetHostViewCreateFunction
g_create_render_widget_host_view = …;
RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
RenderWidgetHostView* view) { … }
class WebDragSourceAura : public content::WebContentsObserver,
public aura::WindowObserver { … };
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
void PrepareDragForFileContents(const DropData& drop_data,
ui::OSExchangeDataProvider* provider) { … }
#endif
#if BUILDFLAG(IS_WIN)
void PrepareDragForDownload(const DropData& drop_data,
ui::OSExchangeDataProvider* provider,
WebContentsImpl* web_contents) {
const GURL& page_url = web_contents->GetLastCommittedURL();
const std::string& page_encoding = web_contents->GetEncoding();
std::u16string mime_type;
base::FilePath file_name;
GURL download_url;
if (!ParseDownloadMetadata(drop_data.download_metadata,
&mime_type,
&file_name,
&download_url))
return;
std::string default_name =
GetContentClient()->browser()->GetDefaultDownloadName();
base::FilePath generated_download_file_name =
net::GenerateFileName(download_url, std::string(), std::string(),
base::WideToUTF8(file_name.value()),
base::UTF16ToUTF8(mime_type), default_name);
ScopedAllowBlockingForViewAura allow_file_operations;
base::FilePath temp_dir_path;
if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
&temp_dir_path))
return;
base::FilePath download_path =
temp_dir_path.Append(generated_download_file_name);
base::DeleteFileAfterReboot(download_path);
base::DeleteFileAfterReboot(temp_dir_path);
auto download_file = std::make_unique<DragDownloadFile>(
download_path, base::File(), download_url,
Referrer(page_url, drop_data.referrer_policy), page_encoding,
provider->GetRendererTaintedOrigin(), web_contents);
ui::DownloadFileInfo file_download(base::FilePath(),
std::move(download_file));
provider->SetDownloadFileInfo(&file_download);
}
#endif
const ui::ClipboardFormatType& GetFileSystemFileFormatType() { … }
void PrepareDragData(const DropData& drop_data,
const url::Origin source_origin,
ui::OSExchangeDataProvider* provider,
WebContentsImpl* web_contents) { … }
#if BUILDFLAG(IS_WIN)
bool ShouldIncludeVirtualFiles(const DropData& drop_data) {
return !drop_data.did_originate_from_renderer && drop_data.url.is_empty();
}
#endif
int ConvertFromDragOperationsMask(blink::DragOperationsMask ops) { … }
blink::DragOperationsMask ConvertToDragOperationsMask(int drag_op) { … }
GlobalRoutingID GetRenderViewHostID(RenderViewHost* rvh) { … }
aura::Window* GetHostWindow(aura::Window* window) { … }
}
WebContentsViewAura::DropMetadata::DropMetadata(
const ui::DropTargetEvent& event) { … }
WebContentsViewAura::OnPerformingDropContext::OnPerformingDropContext(
RenderWidgetHostImpl* target_rwh,
std::unique_ptr<DropData> drop_data,
DropMetadata drop_metadata,
std::unique_ptr<ui::OSExchangeData> data,
base::ScopedClosureRunner end_drag_runner,
std::optional<gfx::PointF> transformed_pt,
gfx::PointF screen_pt)
: … { … }
WebContentsViewAura::OnPerformingDropContext::OnPerformingDropContext(
OnPerformingDropContext&&) = default;
WebContentsViewAura::OnPerformingDropContext::~OnPerformingDropContext() =
default;
#if BUILDFLAG(IS_WIN)
class WebContentsViewAura::AsyncDropNavigationObserver
: public WebContentsObserver {
public:
explicit AsyncDropNavigationObserver(WebContents* watched_contents);
AsyncDropNavigationObserver(const AsyncDropNavigationObserver&) = delete;
AsyncDropNavigationObserver& operator=(const AsyncDropNavigationObserver&) =
delete;
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
bool drop_allowed() const { return drop_allowed_; }
private:
bool drop_allowed_ = true;
};
WebContentsViewAura::AsyncDropNavigationObserver::AsyncDropNavigationObserver(
WebContents* watched_contents)
: WebContentsObserver(watched_contents) {}
void WebContentsViewAura::AsyncDropNavigationObserver::DidFinishNavigation(
NavigationHandle* navigation_handle) {
auto* navigation_request = NavigationRequest::From(navigation_handle);
if (navigation_request->HasCommitted() &&
(navigation_request->GetURL() !=
navigation_request->GetPreviousMainFrameURL()) &&
navigation_request->GetRenderFrameHost()->GetLifecycleState() !=
RenderFrameHost::LifecycleState::kPrerendering) {
drop_allowed_ = false;
}
}
class WebContentsViewAura::AsyncDropTempFileDeleter {
public:
AsyncDropTempFileDeleter() = default;
AsyncDropTempFileDeleter(const AsyncDropTempFileDeleter&) = delete;
AsyncDropTempFileDeleter& operator=(const AsyncDropTempFileDeleter&) = delete;
~AsyncDropTempFileDeleter();
void RegisterFile(const base::FilePath& path);
private:
void DeleteAllFilesAsync() const;
void DeleteFileAsync(const base::FilePath& path) const;
std::vector<base::FilePath> scoped_files_to_delete_;
};
WebContentsViewAura::AsyncDropTempFileDeleter::~AsyncDropTempFileDeleter() {
DeleteAllFilesAsync();
}
void WebContentsViewAura::AsyncDropTempFileDeleter::RegisterFile(
const base::FilePath& path) {
scoped_files_to_delete_.push_back(path);
}
void WebContentsViewAura::AsyncDropTempFileDeleter::DeleteAllFilesAsync()
const {
for (const auto& path : scoped_files_to_delete_)
DeleteFileAsync(path);
}
void WebContentsViewAura::AsyncDropTempFileDeleter::DeleteFileAsync(
const base::FilePath& path) const {
base::ThreadPool::PostTask(FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::GetDeleteFileCallback(std::move(path)));
}
#endif
class WebContentsViewAura::WindowObserver
: public aura::WindowObserver, public aura::WindowTreeHostObserver { … };
void WebContentsViewAura::InstallCreateHookForTests(
RenderWidgetHostViewCreateFunction create_render_widget_host_view) { … }
WebContentsViewAura::WebContentsViewAura(
WebContentsImpl* web_contents,
std::unique_ptr<WebContentsViewDelegate> delegate)
: … { … }
WebContentsViewAura::~WebContentsViewAura() { … }
void WebContentsViewAura::SetDelegateForTesting(
std::unique_ptr<WebContentsViewDelegate> delegate) { … }
void WebContentsViewAura::PrepareDropData(
DropData* drop_data,
const ui::OSExchangeData& data) const { … }
void WebContentsViewAura::EndDrag(
base::WeakPtr<RenderWidgetHostImpl> source_rwh_weak_ptr,
DragOperation op) { … }
void WebContentsViewAura::InstallOverscrollControllerDelegate(
RenderWidgetHostViewAura* view) { … }
ui::TouchSelectionController* WebContentsViewAura::GetSelectionController()
const { … }
TouchSelectionControllerClientAura*
WebContentsViewAura::GetSelectionControllerClient() const { … }
gfx::NativeView WebContentsViewAura::GetRenderWidgetHostViewParent() const { … }
gfx::NativeView WebContentsViewAura::GetNativeView() const { … }
gfx::NativeView WebContentsViewAura::GetContentNativeView() const { … }
gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const { … }
gfx::Rect WebContentsViewAura::GetContainerBounds() const { … }
void WebContentsViewAura::Focus() { … }
void WebContentsViewAura::SetInitialFocus() { … }
void WebContentsViewAura::StoreFocus() { … }
void WebContentsViewAura::RestoreFocus() { … }
void WebContentsViewAura::FocusThroughTabTraversal(bool reverse) { … }
DropData* WebContentsViewAura::GetDropData() const { … }
gfx::Rect WebContentsViewAura::GetViewBounds() const { … }
void WebContentsViewAura::CreateAuraWindow(aura::Window* context) { … }
void WebContentsViewAura::UpdateWebContentsVisibility() { … }
Visibility WebContentsViewAura::GetVisibility() const { … }
void WebContentsViewAura::CreateView(gfx::NativeView context) { … }
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
RenderWidgetHost* render_widget_host) { … }
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) { … }
void WebContentsViewAura::SetPageTitle(const std::u16string& title) { … }
void WebContentsViewAura::RenderViewReady() { … }
void WebContentsViewAura::RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) { … }
void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) { … }
void WebContentsViewAura::OnCapturerCountChanged() { … }
void WebContentsViewAura::FullscreenStateChanged(bool is_fullscreen) { … }
void WebContentsViewAura::UpdateWindowControlsOverlay(
const gfx::Rect& bounding_rect) { … }
BackForwardTransitionAnimationManager*
WebContentsViewAura::GetBackForwardTransitionAnimationManager() { … }
void WebContentsViewAura::ShowContextMenu(RenderFrameHost& render_frame_host,
const ContextMenuParams& params) { … }
void WebContentsViewAura::StartDragging(
const DropData& drop_data,
const url::Origin& source_origin,
blink::DragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& cursor_offset,
const gfx::Rect& drag_obj_rect,
const blink::mojom::DragEventSourceInfo& event_info,
RenderWidgetHostImpl* source_rwh) { … }
void WebContentsViewAura::UpdateDragOperation(DragOperation operation,
bool document_is_handling_drag) { … }
void WebContentsViewAura::GotFocus(RenderWidgetHostImpl* render_widget_host) { … }
void WebContentsViewAura::LostFocus(RenderWidgetHostImpl* render_widget_host) { … }
void WebContentsViewAura::TakeFocus(bool reverse) { … }
gfx::Size WebContentsViewAura::GetMinimumSize() const { … }
gfx::Size WebContentsViewAura::GetMaximumSize() const { … }
void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) { … }
gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) { … }
int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const { … }
bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
aura::Window* child,
const gfx::Point& location) { … }
bool WebContentsViewAura::CanFocus() { … }
void WebContentsViewAura::OnCaptureLost() { … }
void WebContentsViewAura::OnPaint(const ui::PaintContext& context) { … }
void WebContentsViewAura::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
float new_device_scale_factor) { … }
void WebContentsViewAura::OnWindowDestroying(aura::Window* window) { … }
void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) { … }
void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) { … }
void WebContentsViewAura::OnWindowOcclusionChanged(
aura::Window::OcclusionState old_occlusion_state,
aura::Window::OcclusionState new_occlusion_state) { … }
bool WebContentsViewAura::HasHitTestMask() const { … }
void WebContentsViewAura::GetHitTestMask(SkPath* mask) const { … }
void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) { … }
void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) { … }
void WebContentsViewAura::DragEnteredCallback(
DropMetadata drop_metadata,
std::unique_ptr<DropData> drop_data,
base::WeakPtr<RenderWidgetHostViewBase> target,
std::optional<gfx::PointF> transformed_pt) { … }
void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) { … }
void WebContentsViewAura::DragUpdatedCallback(
DropMetadata drop_metadata,
std::unique_ptr<DropData> drop_data,
base::WeakPtr<RenderWidgetHostViewBase> target,
std::optional<gfx::PointF> transformed_pt) { … }
aura::client::DragUpdateInfo WebContentsViewAura::OnDragUpdated(
const ui::DropTargetEvent& event) { … }
void WebContentsViewAura::OnDragExited() { … }
void WebContentsViewAura::CompleteDragExit() { … }
void WebContentsViewAura::PerformDropCallback(
DropMetadata drop_metadata,
std::unique_ptr<ui::OSExchangeData> data,
base::WeakPtr<RenderWidgetHostViewBase> target,
std::optional<gfx::PointF> transformed_pt) { … }
void WebContentsViewAura::MaybeLetDelegateProcessDrop(
OnPerformingDropContext drop_context) { … }
void WebContentsViewAura::GotModifiedDropDataFromDelegate(
OnPerformingDropContext drop_context,
std::optional<DropData> drop_data) { … }
aura::client::DragDropDelegate::DropCallback
WebContentsViewAura::GetDropCallback(const ui::DropTargetEvent& event) { … }
void WebContentsViewAura::CompleteDrop(OnPerformingDropContext drop_context) { … }
void WebContentsViewAura::PerformDropOrExitDrag(
base::ScopedClosureRunner exit_drag,
DropMetadata drop_metadata,
std::unique_ptr<ui::OSExchangeData> data,
ui::mojom::DragOperation& output_drag_op,
std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner) { … }
void WebContentsViewAura::RegisterDropCallbackForTesting(
DropCallbackForTesting callback) { … }
#if BUILDFLAG(IS_WIN)
void WebContentsViewAura::OnGotVirtualFilesAsTempFiles(
OnPerformingDropContext drop_context,
const std::vector<std::pair<base::FilePath, base::FilePath>>&
filepaths_and_names) {
if (!async_drop_navigation_observer_) {
return;
}
if (!filepaths_and_names.empty()) {
std::unique_ptr<AsyncDropNavigationObserver> drop_observer(
std::move(async_drop_navigation_observer_));
RenderWidgetHostImpl* target_rwh = drop_context.target_rwh.get();
if (!drop_observer->drop_allowed() ||
!(target_rwh && target_rwh == current_rwh_for_drag_.get() &&
drag_security_info_.IsValidDragTarget(target_rwh))) {
if (!drop_callback_for_testing_.is_null()) {
std::move(drop_callback_for_testing_)
.Run(target_rwh, *drop_context.drop_data,
drop_context.transformed_pt.value(), drop_context.screen_pt,
drop_context.drop_metadata.flags,
drop_observer->drop_allowed());
}
CompleteDragExit();
return;
}
drop_context.drop_data->filenames.clear();
if (!async_drop_temp_file_deleter_) {
async_drop_temp_file_deleter_ =
std::make_unique<AsyncDropTempFileDeleter>();
}
for (const auto& filepath_and_name : filepaths_and_names) {
drop_context.drop_data->filenames.push_back(
ui::FileInfo(filepath_and_name.first, filepath_and_name.second));
async_drop_temp_file_deleter_->RegisterFile(filepath_and_name.first);
}
}
MaybeLetDelegateProcessDrop(std::move(drop_context));
}
#endif
int WebContentsViewAura::GetTopControlsHeight() const { … }
int WebContentsViewAura::GetBottomControlsHeight() const { … }
bool WebContentsViewAura::DoBrowserControlsShrinkRendererSize() const { … }
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
void WebContentsViewAura::ShowPopupMenu(
RenderFrameHost* render_frame_host,
mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client,
const gfx::Rect& bounds,
int item_height,
double item_font_size,
int selected_item,
std::vector<blink::mojom::MenuItemPtr> menu_items,
bool right_aligned,
bool allow_multiple_selection) {
NOTIMPLEMENTED() << " show " << menu_items.size() << " menu items";
}
#endif
}