Skip to content

Commit

Permalink
refactor: mojofy autofill renderer->browser (#18760)
Browse files Browse the repository at this point in the history
* re-implement renderer->browser calls with mojo

* lint

* fix: clean up after rebase

* lint

* fix: lazy load autofill drivers
  • Loading branch information
brenca authored and codebytere committed Aug 19, 2019
1 parent 43e6d7f commit b33558d
Show file tree
Hide file tree
Showing 14 changed files with 329 additions and 98 deletions.
4 changes: 4 additions & 0 deletions filenames.gni
Expand Up @@ -125,6 +125,10 @@ filenames = {
"shell/browser/auto_updater.cc",
"shell/browser/auto_updater.h",
"shell/browser/auto_updater_mac.mm",
"shell/browser/atom_autofill_driver_factory.cc",
"shell/browser/atom_autofill_driver_factory.h",
"shell/browser/atom_autofill_driver.cc",
"shell/browser/atom_autofill_driver.h",
"shell/browser/atom_blob_reader.cc",
"shell/browser/atom_blob_reader.h",
"shell/browser/atom_browser_client.cc",
Expand Down
43 changes: 10 additions & 33 deletions shell/browser/api/atom_api_web_contents.cc
Expand Up @@ -50,6 +50,7 @@
#include "shell/browser/api/atom_api_browser_window.h"
#include "shell/browser/api/atom_api_debugger.h"
#include "shell/browser/api/atom_api_session.h"
#include "shell/browser/atom_autofill_driver_factory.h"
#include "shell/browser/atom_browser_client.h"
#include "shell/browser/atom_browser_context.h"
#include "shell/browser/atom_browser_main_parts.h"
Expand Down Expand Up @@ -471,6 +472,7 @@ void WebContents::InitWithSessionAndOptions(
base::Unretained(this)));
bindings_.set_connection_error_handler(base::BindRepeating(
&WebContents::OnElectronBrowserConnectionError, base::Unretained(this)));
AutofillDriverFactory::CreateForWebContents(web_contents());

web_contents()->SetUserAgentOverride(GetBrowserContext()->GetUserAgent(),
false);
Expand Down Expand Up @@ -626,7 +628,13 @@ void WebContents::SetContentsBounds(content::WebContents* source,

void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
HideAutofillPopup();

auto* autofill_driver_factory =
AutofillDriverFactory::FromWebContents(web_contents());
if (autofill_driver_factory) {
autofill_driver_factory->CloseAllPopups();
}

if (managed_web_contents())
managed_web_contents()->GetView()->SetDelegate(nullptr);
for (ExtendedWebContentsObserver& observer : observers_)
Expand Down Expand Up @@ -1153,26 +1161,6 @@ void WebContents::DevToolsClosed() {
Emit("devtools-closed");
}

void WebContents::ShowAutofillPopup(content::RenderFrameHost* frame_host,
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
bool offscreen = IsOffScreen() || (embedder_ && embedder_->IsOffScreen());
gfx::RectF popup_bounds(bounds);
content::RenderFrameHost* embedder_frame_host = nullptr;
if (embedder_) {
auto* embedder_view = embedder_->web_contents()->GetMainFrame()->GetView();
auto* view = web_contents()->GetMainFrame()->GetView();
auto offset = view->GetViewBounds().origin() -
embedder_view->GetViewBounds().origin();
popup_bounds.Offset(offset.x(), offset.y());
embedder_frame_host = embedder_->web_contents()->GetMainFrame();
}

CommonWebContentsDelegate::ShowAutofillPopup(
frame_host, embedder_frame_host, offscreen, popup_bounds, values, labels);
}

bool WebContents::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
Expand Down Expand Up @@ -2214,17 +2202,6 @@ void WebContents::DoGetZoomLevel(DoGetZoomLevelCallback callback) {
std::move(callback).Run(GetZoomLevel());
}

void WebContents::ShowAutofillPopup(const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
content::RenderFrameHost* frame_host = bindings_.dispatch_context();
ShowAutofillPopup(frame_host, bounds, values, labels);
}

void WebContents::HideAutofillPopup() {
CommonWebContentsDelegate::HideAutofillPopup();
}

std::vector<base::FilePath::StringType> WebContents::GetPreloadPaths() const {
auto result = SessionPreferences::GetValidPreloads(GetBrowserContext());

Expand Down Expand Up @@ -2279,7 +2256,7 @@ v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, session_);
}

content::WebContents* WebContents::HostWebContents() {
content::WebContents* WebContents::HostWebContents() const {
if (!embedder_)
return nullptr;
return embedder_->web_contents();
Expand Down
18 changes: 4 additions & 14 deletions shell/browser/api/atom_api_web_contents.h
Expand Up @@ -14,6 +14,7 @@
#include "base/observer_list_types.h"
#include "content/common/cursors/webcursor.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/browser/web_contents_observer.h"
Expand All @@ -27,7 +28,6 @@
#include "shell/browser/api/save_page_handler.h"
#include "shell/browser/api/trackable_object.h"
#include "shell/browser/common_web_contents_delegate.h"
#include "shell/browser/ui/autofill_popup.h"
#include "ui/gfx/image/image.h"

#if BUILDFLAG(ENABLE_PRINTING)
Expand Down Expand Up @@ -305,7 +305,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Properties.
int32_t ID() const;
v8::Local<v8::Value> Session(v8::Isolate* isolate);
content::WebContents* HostWebContents();
content::WebContents* HostWebContents() const;
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);

Expand All @@ -323,6 +323,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
bool EmitNavigationEvent(const std::string& event,
content::NavigationHandle* navigation_handle);

WebContents* embedder() { return embedder_; }

protected:
// Does not manage lifetime of |web_contents|.
WebContents(v8::Isolate* isolate, content::WebContents* web_contents);
Expand Down Expand Up @@ -469,13 +471,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
void DevToolsOpened() override;
void DevToolsClosed() override;

#if defined(TOOLKIT_VIEWS)
void ShowAutofillPopup(content::RenderFrameHost* frame_host,
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels);
#endif

private:
AtomBrowserContext* GetBrowserContext() const;

Expand Down Expand Up @@ -514,11 +509,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
void SetTemporaryZoomLevel(double level) override;
void DoGetZoomLevel(DoGetZoomLevelCallback callback) override;

void ShowAutofillPopup(const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) override;
void HideAutofillPopup() override;

// Called when we receive a CursorChange message from chromium.
void OnCursorChange(const content::WebCursor& cursor);

Expand Down
63 changes: 63 additions & 0 deletions shell/browser/atom_autofill_driver.cc
@@ -0,0 +1,63 @@
// Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/browser/atom_autofill_driver.h"

#include <utility>

#include "content/public/browser/render_widget_host_view.h"
#include "shell/browser/api/atom_api_web_contents.h"
#include "shell/browser/native_window.h"

namespace electron {

AutofillDriver::AutofillDriver(
content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request)
: render_frame_host_(render_frame_host), binding_(this) {
autofill_popup_.reset(new AutofillPopup());
binding_.Bind(std::move(request));
}

AutofillDriver::~AutofillDriver() {}

void AutofillDriver::ShowAutofillPopup(
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
auto* web_contents =
api::WebContents::From(
v8::Isolate::GetCurrent(),
content::WebContents::FromRenderFrameHost(render_frame_host_))
.get();
if (!web_contents || !web_contents->owner_window())
return;

auto* embedder = web_contents->embedder();

bool osr =
web_contents->IsOffScreen() || (embedder && embedder->IsOffScreen());
gfx::RectF popup_bounds(bounds);
content::RenderFrameHost* embedder_frame_host = nullptr;
if (embedder) {
auto* embedder_view = embedder->web_contents()->GetMainFrame()->GetView();
auto* view = web_contents->web_contents()->GetMainFrame()->GetView();
auto offset = view->GetViewBounds().origin() -
embedder_view->GetViewBounds().origin();
popup_bounds.Offset(offset.x(), offset.y());
embedder_frame_host = embedder->web_contents()->GetMainFrame();
}

autofill_popup_->CreateView(render_frame_host_, embedder_frame_host, osr,
web_contents->owner_window()->content_view(),
bounds);
autofill_popup_->SetItems(values, labels);
}

void AutofillDriver::HideAutofillPopup() {
if (autofill_popup_)
autofill_popup_->Hide();
}

} // namespace electron
44 changes: 44 additions & 0 deletions shell/browser/atom_autofill_driver.h
@@ -0,0 +1,44 @@
// Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#ifndef SHELL_BROWSER_ATOM_AUTOFILL_DRIVER_H_
#define SHELL_BROWSER_ATOM_AUTOFILL_DRIVER_H_

#include <memory>
#include <vector>

#if defined(TOOLKIT_VIEWS)
#include "shell/browser/ui/autofill_popup.h"
#endif

#include "mojo/public/cpp/bindings/associated_binding.h"
#include "shell/common/api/api.mojom.h"

namespace electron {

class AutofillDriver : public mojom::ElectronAutofillDriver {
public:
AutofillDriver(content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request);

~AutofillDriver() override;

void ShowAutofillPopup(const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) override;
void HideAutofillPopup() override;

private:
content::RenderFrameHost* const render_frame_host_;

#if defined(TOOLKIT_VIEWS)
std::unique_ptr<AutofillPopup> autofill_popup_;
#endif

mojo::AssociatedBinding<mojom::ElectronAutofillDriver> binding_;
};

} // namespace electron

#endif // SHELL_BROWSER_ATOM_AUTOFILL_DRIVER_H_
111 changes: 111 additions & 0 deletions shell/browser/atom_autofill_driver_factory.cc
@@ -0,0 +1,111 @@
// Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/browser/atom_autofill_driver_factory.h"

#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "shell/browser/atom_autofill_driver.h"

namespace electron {

namespace {

std::unique_ptr<AutofillDriver> CreateDriver(
content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request) {
return std::make_unique<AutofillDriver>(render_frame_host,
std::move(request));
}

} // namespace

AutofillDriverFactory::~AutofillDriverFactory() {}

// static
void AutofillDriverFactory::BindAutofillDriver(
mojom::ElectronAutofillDriverAssociatedRequest request,
content::RenderFrameHost* render_frame_host) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
if (!web_contents)
return;

AutofillDriverFactory* factory =
AutofillDriverFactory::FromWebContents(web_contents);
if (!factory)
return;

AutofillDriver* driver = factory->DriverForFrame(render_frame_host);
if (!driver)
factory->AddDriverForFrame(
render_frame_host,
base::BindOnce(CreateDriver, render_frame_host, std::move(request)));
}

AutofillDriverFactory::AutofillDriverFactory(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
const std::vector<content::RenderFrameHost*> frames =
web_contents->GetAllFrames();
for (content::RenderFrameHost* frame : frames) {
if (frame->IsRenderFrameLive())
RenderFrameCreated(frame);
}
}

void AutofillDriverFactory::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
DeleteDriverForFrame(render_frame_host);
}

void AutofillDriverFactory::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
// For the purposes of this code, a navigation is not important if it has not
// committed yet or if it's in a subframe.
if (!navigation_handle->HasCommitted() ||
!navigation_handle->IsInMainFrame()) {
return;
}

CloseAllPopups();
}

AutofillDriver* AutofillDriverFactory::DriverForFrame(
content::RenderFrameHost* render_frame_host) {
auto mapping = driver_map_.find(render_frame_host);
return mapping == driver_map_.end() ? nullptr : mapping->second.get();
}

void AutofillDriverFactory::AddDriverForFrame(
content::RenderFrameHost* render_frame_host,
CreationCallback factory_method) {
auto insertion_result =
driver_map_.insert(std::make_pair(render_frame_host, nullptr));
// This can be called twice for the key representing the main frame.
if (insertion_result.second) {
insertion_result.first->second = std::move(factory_method).Run();
}
}

void AutofillDriverFactory::DeleteDriverForFrame(
content::RenderFrameHost* render_frame_host) {
driver_map_.erase(render_frame_host);
}

void AutofillDriverFactory::CloseAllPopups() {
for (auto& it : driver_map_) {
it.second->HideAutofillPopup();
}
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(AutofillDriverFactory)

} // namespace electron

0 comments on commit b33558d

Please sign in to comment.