blob: bd1491937702766b5079418774b66fc384ae9912 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/crosapi_new_window_delegate.h"
#include "base/logging.h"
#include "chrome/browser/ash/crosapi/browser_manager.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/crosapi/window_util.h"
#include "chrome/browser/ui/ash/chrome_new_window_client.h"
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/base/dragdrop/os_exchange_data.h"
namespace {
crosapi::mojom::OpenUrlFrom OpenUrlFromToMojom(
ash::NewWindowDelegate::OpenUrlFrom from) {
switch (from) {
case ash::NewWindowDelegate::OpenUrlFrom::kUnspecified:
case ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction:
return crosapi::mojom::OpenUrlFrom::kUnspecified;
case ash::NewWindowDelegate::OpenUrlFrom::kArc:
return crosapi::mojom::OpenUrlFrom::kArc;
}
}
crosapi::mojom::OpenUrlParams::WindowOpenDisposition DispositionToMojom(
ash::NewWindowDelegate::Disposition disposition) {
switch (disposition) {
case ash::NewWindowDelegate::Disposition::kNewForegroundTab:
return crosapi::mojom::OpenUrlParams::WindowOpenDisposition::
kNewForegroundTab;
case ash::NewWindowDelegate::Disposition::kNewWindow:
return crosapi::mojom::OpenUrlParams::WindowOpenDisposition::kNewWindow;
case ash::NewWindowDelegate::Disposition::kSwitchToTab:
return crosapi::mojom::OpenUrlParams::WindowOpenDisposition::kSwitchToTab;
}
}
} // namespace
CrosapiNewWindowDelegate::WindowObserver::WindowObserver(
CrosapiNewWindowDelegate* owner,
NewWindowForDetachingTabCallback closure)
: owner_(owner), closure_(std::move(closure)) {
// This object is instantiated before the relevant aura::Windows are created.
exo::WMHelper::GetInstance()->AddExoWindowObserver(this);
}
CrosapiNewWindowDelegate::WindowObserver::~WindowObserver() {
windows_committed_prior_to_window_id_.clear();
exo::WMHelper::GetInstance()->RemoveExoWindowObserver(this);
if (!closure_.is_null())
std::move(closure_).Run(/*new_window=*/nullptr);
}
void CrosapiNewWindowDelegate::WindowObserver::OnExoWindowCreated(
aura::Window* new_window) {
if (observed_windows_.IsObservingSource(new_window))
return;
observed_windows_.AddObservation(new_window);
}
void CrosapiNewWindowDelegate::WindowObserver::OnWindowVisibilityChanged(
aura::Window* window,
bool visible) {
if (!window || !visible || closure_.is_null())
return;
// In case the |window_id_| has not been set yet, record the all window for
// future iteration.
if (window_id_.empty()) {
windows_committed_prior_to_window_id_.insert(window);
return;
}
if (crosapi::GetShellSurfaceWindow(window_id_) == window) {
std::move(closure_).Run(window);
owner_->DestroyWindowObserver();
return;
}
}
void CrosapiNewWindowDelegate::WindowObserver::SetWindowID(
const std::string& window_id) {
window_id_ = window_id;
// Handle the scenario where the exo::kSurfacePendingCommitKey property
// is set prior to the |window_id_|.
if (windows_committed_prior_to_window_id_.empty())
return;
auto* window = crosapi::GetShellSurfaceWindow(window_id_);
for (auto* it : windows_committed_prior_to_window_id_) {
if (window == it) {
std::move(closure_).Run(window);
owner_->DestroyWindowObserver();
return;
}
}
}
CrosapiNewWindowDelegate::CrosapiNewWindowDelegate(
ash::NewWindowDelegate* delegate)
: delegate_(delegate) {}
CrosapiNewWindowDelegate::~CrosapiNewWindowDelegate() = default;
void CrosapiNewWindowDelegate::NewTab() {
crosapi::BrowserManager::Get()->NewTab(
/*should_trigger_session_restore=*/false);
}
void CrosapiNewWindowDelegate::NewWindow(bool incognito,
bool should_trigger_session_restore) {
crosapi::BrowserManager::Get()->NewWindow(incognito,
should_trigger_session_restore);
}
void CrosapiNewWindowDelegate::NewWindowForDetachingTab(
aura::Window* source_window,
const ui::OSExchangeData& drop_data,
NewWindowForDetachingTabCallback closure) {
if (crosapi::browser_util::IsLacrosWindow(source_window)) {
std::u16string tab_id_str;
std::u16string group_id_str;
if (!tab_strip_ui::ExtractTabData(drop_data, &tab_id_str, &group_id_str)) {
std::move(closure).Run(/*new_window=*/nullptr);
return;
}
window_observer_ =
std::make_unique<WindowObserver>(this, std::move(closure));
// The window will be created on lacros side.
// Post-creation routines, like split view / window snap handling need be
// performed later.
auto callback = base::BindOnce(
[](WindowObserver* observer, crosapi::mojom::CreationResult result,
const std::string& window_id) { observer->SetWindowID(window_id); },
window_observer_.get());
crosapi::BrowserManager::Get()->NewWindowForDetachingTab(
tab_id_str, group_id_str, std::move(callback));
return;
}
delegate_->NewWindowForDetachingTab(source_window, drop_data,
std::move(closure));
}
void CrosapiNewWindowDelegate::OpenUrl(const GURL& url,
OpenUrlFrom from,
Disposition disposition) {
crosapi::BrowserManager::Get()->OpenUrl(url, OpenUrlFromToMojom(from),
DispositionToMojom(disposition));
}
void CrosapiNewWindowDelegate::OpenCalculator() {
delegate_->OpenCalculator();
}
void CrosapiNewWindowDelegate::OpenFileManager() {
delegate_->OpenFileManager();
}
void CrosapiNewWindowDelegate::OpenDownloadsFolder() {
delegate_->OpenDownloadsFolder();
}
void CrosapiNewWindowDelegate::OpenCrosh() {
delegate_->OpenCrosh();
}
void CrosapiNewWindowDelegate::OpenGetHelp() {
delegate_->OpenGetHelp();
}
void CrosapiNewWindowDelegate::RestoreTab() {
crosapi::BrowserManager::Get()->RestoreTab();
}
void CrosapiNewWindowDelegate::ShowKeyboardShortcutViewer() {
delegate_->ShowKeyboardShortcutViewer();
}
void CrosapiNewWindowDelegate::ShowTaskManager() {
delegate_->ShowTaskManager();
}
void CrosapiNewWindowDelegate::OpenDiagnostics() {
delegate_->OpenDiagnostics();
}
void CrosapiNewWindowDelegate::OpenFeedbackPage(
FeedbackSource source,
const std::string& description_template) {
delegate_->OpenFeedbackPage(source, description_template);
}
void CrosapiNewWindowDelegate::OpenPersonalizationHub() {
delegate_->OpenPersonalizationHub();
}
void CrosapiNewWindowDelegate::DestroyWindowObserver() {
window_observer_.reset();
}