mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-01-29 18:49:52 +01:00
dca0435d2f
Split the Alloy runtime into bootstrap and style components. Support creation of Alloy style browsers and windows with the Chrome runtime. Chrome runtime (`--enable-chrome-runtime`) + Alloy style (`--use-alloy-style`) supports Views (`--use-views`), native parent (`--use-native`) and windowless rendering (`--off-screen-rendering-enabled`). Print preview is supported in all cases except with windowless rendering on all platforms and native parent on MacOS. It is disabled by default with Alloy style for legacy compatibility. Where supported it can be enabled or disabled globally using `--[enable|disable]-print-preview` or configured on a per-RequestContext basis using the `printing.print_preview_disabled` preference. It also behaves as expected when triggered via the PDF viewer print button. Chrome runtime + Alloy style behavior differs from Alloy runtime in the following significant ways: - Supports Chrome error pages by default. - DevTools popups are Chrome style only (cannot be windowless). - The Alloy extension API will not supported. Chrome runtime + Alloy style passes all expected Alloy ceftests except the following: - `DisplayTest.AutoResize` (Alloy extension API not supported) - `DownloadTest.*` (Download API not yet supported) - `ExtensionTest.*` (Alloy extension API not supported) This change also adds Chrome runtime support for CefContextMenuHandler::RunContextMenu (see #3293). This change also explicitly blocks (and doesn't retry) FrameAttached requests from PDF viewer and print preview excluded frames (see #3664). Known issues specific to Chrome runtime + Alloy style: - DevTools popup with windowless rendering doesn't load successfully. Use windowed rendering or remote debugging as a workaround. - Chrome style Window with Alloy style BrowserView (`--use-alloy-style --use-chrome-style-window`) does not show Chrome theme changes. To test: - Run `ceftests --enable-chrome-runtime --use-alloy-style [--use-chrome-style-window] [--use-views|--use-native] --gtest_filter=...` - Run `cefclient --enable-chrome-runtime --use-alloy-style [--use-chrome-style-window] [--use-views|--use-native|--off-screen-rendering-enabled]` - Run `cefsimple --enable-chrome-runtime --use-alloy-style [--use-views]`
152 lines
5.3 KiB
C++
152 lines
5.3 KiB
C++
// Copyright (c) 2022 The Chromium Embedded Framework Authors.
|
|
// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "libcef/browser/file_dialog_runner.h"
|
|
|
|
#include "chrome/browser/file_select_helper.h"
|
|
#include "chrome/browser/ui/chrome_select_file_policy.h"
|
|
#include "libcef/browser/browser_host_base.h"
|
|
#include "ui/shell_dialogs/select_file_dialog_factory.h"
|
|
#include "ui/shell_dialogs/select_file_policy.h"
|
|
|
|
using blink::mojom::FileChooserParams;
|
|
|
|
namespace {
|
|
|
|
// Creation of a file dialog can be triggered via various code paths, but they
|
|
// all eventually result in a call to ui::SelectFileDialog::Create. We intercept
|
|
// that call with CefSelectFileDialogFactory and redirect it to
|
|
// CefFileDialogManager::RunSelectFile. After triggering the CefDialogHandler
|
|
// callbacks that method calls ui::SelectFileDialog::Create again with
|
|
// |run_from_cef=false| to trigger creation of the default platform dialog.
|
|
class CefSelectFileDialogFactory final : public ui::SelectFileDialogFactory {
|
|
public:
|
|
CefSelectFileDialogFactory() = default;
|
|
|
|
CefSelectFileDialogFactory(const CefSelectFileDialogFactory&) = delete;
|
|
CefSelectFileDialogFactory& operator=(const CefSelectFileDialogFactory&) =
|
|
delete;
|
|
|
|
ui::SelectFileDialog* Create(
|
|
ui::SelectFileDialog::Listener* listener,
|
|
std::unique_ptr<ui::SelectFilePolicy> policy) override;
|
|
|
|
bool IsCefFactory() const override { return true; }
|
|
};
|
|
|
|
// Delegates the running of the dialog to CefFileDialogManager.
|
|
class CefSelectFileDialog final : public ui::SelectFileDialog {
|
|
public:
|
|
CefSelectFileDialog(ui::SelectFileDialog::Listener* listener,
|
|
std::unique_ptr<ui::SelectFilePolicy> policy)
|
|
: ui::SelectFileDialog(listener, std::move(policy)) {
|
|
DCHECK(listener_);
|
|
}
|
|
|
|
CefSelectFileDialog(const CefSelectFileDialog&) = delete;
|
|
CefSelectFileDialog& operator=(const CefSelectFileDialog&) = delete;
|
|
|
|
void SelectFileImpl(Type type,
|
|
const std::u16string& title,
|
|
const base::FilePath& default_path,
|
|
const FileTypeInfo* file_types,
|
|
int file_type_index,
|
|
const base::FilePath::StringType& default_extension,
|
|
gfx::NativeWindow owning_window,
|
|
void* params,
|
|
const GURL* caller) override {
|
|
// Try to determine the associated browser (with decreasing levels of
|
|
// confidence).
|
|
// 1. Browser associated with the SelectFilePolicy. This is the most
|
|
// reliable mechanism if specified at the SelectFileDialog::Create call
|
|
// site.
|
|
if (select_file_policy_) {
|
|
auto chrome_policy =
|
|
static_cast<ChromeSelectFilePolicy*>(select_file_policy_.get());
|
|
auto web_contents = chrome_policy->source_contents();
|
|
if (web_contents) {
|
|
browser_ = CefBrowserHostBase::GetBrowserForContents(web_contents);
|
|
}
|
|
if (!browser_) {
|
|
LOG(WARNING) << "No browser associated with SelectFilePolicy";
|
|
}
|
|
}
|
|
|
|
// 2. Browser associated with the top-level native window (owning_window).
|
|
// This should be reliable with windowed browsers. However, |owning_window|
|
|
// will always be nullptr with windowless browsers.
|
|
if (!browser_ && owning_window) {
|
|
browser_ =
|
|
CefBrowserHostBase::GetBrowserForTopLevelNativeWindow(owning_window);
|
|
if (!browser_) {
|
|
LOG(WARNING) << "No browser associated with top-level native window";
|
|
}
|
|
}
|
|
|
|
// 3. Browser most likely to be focused. This may be somewhat iffy with
|
|
// windowless browsers as there is no guarantee that the client has only
|
|
// one browser focused at a time.
|
|
if (!browser_) {
|
|
browser_ = CefBrowserHostBase::GetLikelyFocusedBrowser();
|
|
if (!browser_) {
|
|
LOG(WARNING) << "No likely focused browser";
|
|
}
|
|
}
|
|
|
|
if (!browser_) {
|
|
LOG(ERROR)
|
|
<< "Failed to identify associated browser; canceling the file dialog";
|
|
listener_->FileSelectionCanceled(params);
|
|
return;
|
|
}
|
|
|
|
owning_window_ = owning_window;
|
|
has_multiple_file_choices_ =
|
|
file_types ? file_types->extensions.size() > 1 : true;
|
|
|
|
browser_->RunSelectFile(listener_, std::move(select_file_policy_), type,
|
|
title, default_path, file_types, file_type_index,
|
|
default_extension, owning_window, params);
|
|
}
|
|
|
|
bool IsRunning(gfx::NativeWindow owning_window) const override {
|
|
return owning_window == owning_window_;
|
|
}
|
|
|
|
void ListenerDestroyed() override {
|
|
if (browser_) {
|
|
browser_->SelectFileListenerDestroyed(listener_);
|
|
}
|
|
listener_ = nullptr;
|
|
}
|
|
|
|
bool HasMultipleFileTypeChoicesImpl() override {
|
|
return has_multiple_file_choices_;
|
|
}
|
|
|
|
private:
|
|
gfx::NativeWindow owning_window_ = nullptr;
|
|
bool has_multiple_file_choices_ = false;
|
|
|
|
CefRefPtr<CefBrowserHostBase> browser_;
|
|
};
|
|
|
|
ui::SelectFileDialog* CefSelectFileDialogFactory::Create(
|
|
ui::SelectFileDialog::Listener* listener,
|
|
std::unique_ptr<ui::SelectFilePolicy> policy) {
|
|
return new CefSelectFileDialog(listener, std::move(policy));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace file_dialog_runner {
|
|
|
|
void RegisterFactory() {
|
|
ui::SelectFileDialog::SetFactory(
|
|
std::make_unique<CefSelectFileDialogFactory>());
|
|
}
|
|
|
|
} // namespace file_dialog_runner
|