Add support for loading extensions (issue #1947)

- Add CefRequestContext::LoadExtension, CefExtension, CefExtensionHandler and
  related methods/interfaces.
- Add chrome://extensions-support that lists supported Chrome APIs.
- Add CefBrowserHost::SetAutoResizeEnabled and CefDisplayHandler::OnAutoResize
  to support browser resize based on preferred web contents size.
- views: Add support for custom CefMenuButton popups.
- cefclient: Run with `--load-extension=set_page_color` command-line flag for
  an extension loading example. Add `--use-views` on Windows and Linux for an
  even better example.
This commit is contained in:
Marshall Greenblatt
2017-08-03 18:55:19 -04:00
parent 5b12134a45
commit 9cff99dc4e
178 changed files with 10360 additions and 650 deletions

View File

@ -174,7 +174,7 @@ void CefBrowserViewImpl::SetPendingBrowserCreateParams(
DCHECK(!pending_browser_create_params_);
pending_browser_create_params_.reset(new CefBrowserHostImpl::CreateParams());
pending_browser_create_params_->client = client;
pending_browser_create_params_->url = url;
pending_browser_create_params_->url = GURL(url.ToString());
pending_browser_create_params_->settings = settings;
pending_browser_create_params_->request_context = request_context;
}

View File

@ -49,8 +49,25 @@ CEF_BUTTON_IMPL_T class CefButtonImpl : public CEF_VIEW_IMPL_D {
CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetState(cef_button_state_t state) {
CEF_REQUIRE_VALID_RETURN_VOID();
ParentClass::root_view()->SetState(
static_cast<views::Button::ButtonState>(state));
views::Button::ButtonState old_state = ParentClass::root_view()->state();
views::Button::ButtonState new_state =
static_cast<views::Button::ButtonState>(state);
if (ParentClass::root_view()->ink_drop_mode() !=
views::CustomButton::InkDropMode::OFF &&
!ParentClass::root_view()->IsFocusable()) {
// Ink drop state does not get set properly on state change when the button
// is non-focusable.
views::InkDropState ink_state = views::InkDropState::HIDDEN;
if (new_state == views::Button::STATE_PRESSED) {
ink_state = views::InkDropState::ACTIVATED;
} else if (old_state == views::Button::STATE_PRESSED) {
ink_state = views::InkDropState::DEACTIVATED;
}
ParentClass::root_view()->AnimateInkDrop(ink_state, nullptr);
}
ParentClass::root_view()->SetState(new_state);
}
CEF_BUTTON_IMPL_T cef_button_state_t CEF_BUTTON_IMPL_D::GetState() {

View File

@ -56,12 +56,16 @@ CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::StateChanged(
CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::ButtonPressed(
views::Button* sender,
const ui::Event& event) {
// Callback may trigger new animation state.
if (ParentClass::cef_delegate())
ParentClass::cef_delegate()->OnButtonPressed(GetCefButton());
if (ParentClass::ink_drop_mode() != views::CustomButton::InkDropMode::OFF &&
!ParentClass::IsFocusable()) {
// When ink drop is enabled for non-focusable buttons the ink drop state
// does not get reset properly on click, so we do it here explicitly.
!ParentClass::IsFocusable() &&
ParentClass::state() != views::CustomButton::STATE_PRESSED) {
// Ink drop state does not get reset properly on click when the button is
// non-focusable. Reset the ink drop state here if the state has not been
// explicitly set to pressed by the OnButtonPressed callback calling
// SetState (which also sets the ink drop state).
ParentClass::AnimateInkDrop(views::InkDropState::HIDDEN,
ui::LocatedEvent::FromIfValid(&event));
}

View File

@ -4,9 +4,27 @@
#include "libcef/browser/views/menu_button_view.h"
#include "libcef/browser/thread_util.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/menu/menu_config.h"
namespace {
class ButtonPressedLock : public CefMenuButtonPressedLock {
public:
explicit ButtonPressedLock(views::MenuButton* menu_button)
: pressed_lock_(menu_button) {}
private:
views::MenuButton::PressedLock pressed_lock_;
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ButtonPressedLock);
DISALLOW_COPY_AND_ASSIGN(ButtonPressedLock);
};
} // namespace
CefMenuButtonView::CefMenuButtonView(CefMenuButtonDelegate* cef_delegate)
: ParentClass(cef_delegate) {
DCHECK(cef_delegate);
@ -36,5 +54,6 @@ void CefMenuButtonView::OnMenuButtonClicked(views::MenuButton* source,
const gfx::Point& point,
const ui::Event* event) {
cef_delegate()->OnMenuButtonPressed(GetCefMenuButton(),
CefPoint(point.x(), point.y()));
CefPoint(point.x(), point.y()),
new ButtonPressedLock(source));
}

View File

@ -122,6 +122,8 @@ class CefWindowImpl
cef_menu_anchor_position_t anchor_position);
void MenuClosed();
views::Widget* widget() const { return widget_; }
private:
// Create a new implementation object.
// Always call Initialize() after creation.

View File

@ -5,6 +5,7 @@
#include "libcef/browser/views/window_view.h"
#include "libcef/browser/image_impl.h"
#include "libcef/browser/views/window_impl.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/window.h"
@ -249,9 +250,29 @@ void CefWindowView::CreateWidget() {
views::Widget::InitParams params;
params.delegate = this;
params.type = views::Widget::InitParams::TYPE_WINDOW;
bool can_activate = true;
if (cef_delegate())
is_frameless_ = cef_delegate()->IsFrameless(GetCefWindow());
if (cef_delegate()) {
CefRefPtr<CefWindow> cef_window = GetCefWindow();
is_frameless_ = cef_delegate()->IsFrameless(cef_window);
bool is_menu = false;
bool can_activate_menu = true;
CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow(
cef_window, &is_menu, &can_activate_menu);
if (parent_window && !parent_window->IsSame(cef_window)) {
CefWindowImpl* parent_window_impl =
static_cast<CefWindowImpl*>(parent_window.get());
params.parent = view_util::GetNativeWindow(parent_window_impl->widget());
if (is_menu) {
// Don't clip the window to parent bounds.
params.type = views::Widget::InitParams::TYPE_MENU;
can_activate = can_activate_menu;
if (can_activate_menu)
params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
}
}
}
#if defined(OS_WIN)
if (is_frameless_) {
@ -267,8 +288,11 @@ void CefWindowView::CreateWidget() {
DCHECK_EQ(widget, GetWidget());
// |widget| must be top-level for focus handling to work correctly.
DCHECK(widget->is_top_level());
// |widget| must be activatable for focus handling to work correctly.
DCHECK(widget->widget_delegate()->CanActivate());
if (can_activate) {
// |widget| must be activatable for focus handling to work correctly.
DCHECK(widget->widget_delegate()->CanActivate());
}
#if defined(OS_LINUX)
if (is_frameless_) {