Decouple WebContentsDelegate from NativeWindow

This commit is contained in:
Cheng Zhao 2015-06-25 11:07:23 +08:00
parent 5236b0c067
commit fb5fe7a714
10 changed files with 120 additions and 179 deletions

View file

@ -142,12 +142,6 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
} // namespace
WebContents::WebContents(brightray::InspectableWebContents* web_contents)
: WebContents(web_contents->GetWebContents()) {
type_ = BROWSER_WINDOW;
inspectable_web_contents_ = web_contents;
}
WebContents::WebContents(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
guest_opaque_(true),
@ -210,8 +204,12 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
const base::string16& message,
int32 line_no,
const base::string16& source_id) {
Emit("console-message", level, message, line_no, source_id);
return true;
if (type_ == BROWSER_WINDOW) {
return false;
} else {
Emit("console-message", level, message, line_no, source_id);
return true;
}
}
bool WebContents::ShouldCreateWebContents(
@ -223,19 +221,21 @@ bool WebContents::ShouldCreateWebContents(
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) {
Emit("new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
if (type_ == BROWSER_WINDOW)
Emit("-new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
else
Emit("new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
return false;
}
void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
}
content::WebContents* WebContents::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) {
Emit("new-window", params.url, "", params.disposition);
if (type_ == BROWSER_WINDOW)
Emit("-new-window", params.url, "", params.disposition);
else
Emit("new-window", params.url, "", params.disposition);
return nullptr;
}
@ -246,6 +246,31 @@ content::WebContents* WebContents::OpenURLFromTab(
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
}
void WebContents::BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) {
if (type_ == BROWSER_WINDOW)
*proceed_to_fire_unload = proceed;
else
*proceed_to_fire_unload = true;
}
void WebContents::MoveContents(content::WebContents* source,
const gfx::Rect& pos) {
Emit("move", pos);
}
void WebContents::CloseContents(content::WebContents* source) {
Emit("closed");
if (type_ == BROWSER_WINDOW)
owner_window()->CloseContents(source);
}
void WebContents::ActivateContents(content::WebContents* source) {
if (type_ == BROWSER_WINDOW)
owner_window()->CloseContents(source);
}
bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
return type_ == BROWSER_WINDOW;
}
@ -253,12 +278,12 @@ bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
void WebContents::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (!attached())
return;
// Send the unhandled keyboard events back to the embedder to reprocess them.
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
web_contents(), event);
if (type_ == BROWSER_WINDOW) {
owner_window()->HandleKeyboardEvent(source, event);
} else if (type_ == WEB_VIEW && !attached()) {
// Send the unhandled keyboard events back to the embedder.
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(source, event);
}
}
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
@ -272,6 +297,23 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
Emit("leave-html-full-screen");
}
void WebContents::RendererUnresponsive(content::WebContents* source) {
Emit("unresponsive");
if (type_ == BROWSER_WINDOW)
owner_window()->RendererUnresponsive(source);
}
void WebContents::RendererResponsive(content::WebContents* source) {
Emit("responsive");
if (type_ == BROWSER_WINDOW)
owner_window()->RendererResponsive(source);
}
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
int process_id = render_view_host->GetProcess()->GetID();
Emit("render-view-deleted", process_id);
@ -898,21 +940,6 @@ gfx::Size WebContents::GetDefaultSize() const {
}
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) {
// We have an existing WebContents object in JS.
auto existing = TrackableObject::FromWrappedClass(
isolate, web_contents->GetWebContents());
if (existing)
return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
// Otherwise create a new WebContents wrapper object.
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) {

View file

@ -57,8 +57,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
PrintToPDFCallback;
// Create from an existing WebContents.
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents);
@ -136,7 +134,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
}
protected:
explicit WebContents(brightray::InspectableWebContents* web_contents);
explicit WebContents(content::WebContents* web_contents);
explicit WebContents(const mate::Dictionary& options);
~WebContents();
@ -160,10 +157,16 @@ class WebContents : public mate::TrackableObject<WebContents>,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) override;
void CloseContents(content::WebContents* source) override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) override;
void MoveContents(content::WebContents* source,
const gfx::Rect& pos) override;
void CloseContents(content::WebContents* source) override;
void ActivateContents(content::WebContents* contents) override;
bool IsPopupOrPanel(const content::WebContents* source) const override;
void HandleKeyboardEvent(
content::WebContents* source,
@ -171,8 +174,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
// content::WebContentsObserver:
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
void RenderViewDeleted(content::RenderViewHost*) override;
void RenderProcessGone(base::TerminationStatus status) override;
void DocumentLoadedInFrame(

View file

@ -43,6 +43,7 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
mate::Dictionary web_contents_options(isolate, v8::Object::New(isolate));
auto web_contents = WebContents::Create(isolate, web_contents_options);
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
// Creates BrowserWindow.
window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
@ -62,17 +63,6 @@ void Window::OnPageTitleUpdated(bool* prevent_default,
*prevent_default = Emit("page-title-updated", title);
}
void Window::WillCreatePopupWindow(const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
WindowOpenDisposition disposition) {
Emit("-new-window", target_url, frame_name);
}
void Window::WillNavigate(bool* prevent_default, const GURL& url) {
*prevent_default = Emit("-will-navigate", url);
}
void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close");
}
@ -80,6 +70,12 @@ void Window::WillCloseWindow(bool* prevent_default) {
void Window::OnWindowClosed() {
Emit("closed");
if (api_web_contents_) {
api_web_contents_->DestroyWebContents();
api_web_contents_ = nullptr;
web_contents_.Reset();
}
RemoveFromWeakMap();
window_->RemoveObserver(this);
}
@ -153,8 +149,8 @@ void Window::OnDevToolsOpened() {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto handle = WebContents::CreateFrom(isolate(),
window_->GetDevToolsWebContents());
auto handle = WebContents::CreateFrom(
isolate(), api_web_contents_->GetDevToolsWebContents());
devtools_web_contents_.Reset(isolate(), handle.ToV8());
}
@ -178,8 +174,7 @@ mate::Wrappable* Window::New(v8::Isolate* isolate,
}
void Window::Destroy() {
window_->DestroyWebContents();
window_->CloseImmediately();
window_->CloseContents(nullptr);
}
void Window::Close() {

View file

@ -51,11 +51,6 @@ class Window : public mate::TrackableObject<Window>,
// NativeWindowObserver:
void OnPageTitleUpdated(bool* prevent_default,
const std::string& title) override;
void WillCreatePopupWindow(const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
WindowOpenDisposition disposition) override;
void WillNavigate(bool* prevent_default, const GURL& url) override;
void WillCloseWindow(bool* prevent_default) override;
void OnWindowClosed() override;
void OnWindowBlur() override;
@ -151,6 +146,8 @@ class Window : public mate::TrackableObject<Window>,
v8::Global<v8::Value> devtools_web_contents_;
v8::Global<v8::Value> menu_;
api::WebContents* api_web_contents_;
scoped_ptr<NativeWindow> window_;
DISALLOW_COPY_AND_ASSIGN(Window);

View file

@ -12,14 +12,13 @@ BrowserWindow::_init = ->
@setMenu menu if menu?
# Make new windows requested by links behave like "window.open"
@on '-new-window', (event, url, frameName) =>
event.sender = @webContents
@webContents.on '-new-window', (event, url, frameName) ->
options = show: true, width: 800, height: 600
ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
# Redirect "will-navigate" to webContents.
@on '-will-navigate', (event, url) =>
@webContents.emit 'will-navigate', event, url
# window.move(...)
@webContents.on 'move', (event, size) =>
@setSize size
# Redirect focus/blur event to app instance too.
@on 'blur', (event) =>

View file

@ -94,6 +94,7 @@ NativeWindow::NativeWindow(
node_integration_(true),
has_dialog_attached_(false),
zoom_factor_(1.0),
inspectable_web_contents_(inspectable_web_contents),
weak_factory_(this) {
options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_);
@ -341,6 +342,13 @@ void NativeWindow::CloseWebContents() {
web_contents->Close();
}
content::WebContents* NativeWindow::GetWebContents() const {
if (inspectable_web_contents_)
return inspectable_web_contents_->GetWebContents();
else
return nullptr;
}
void NativeWindow::AppendExtraCommandLineSwitches(
base::CommandLine* command_line) {
// Append --node-integration to renderer process.
@ -475,52 +483,6 @@ void NativeWindow::NotifyWindowLeaveHtmlFullScreen() {
OnWindowLeaveHtmlFullScreen());
}
bool NativeWindow::ShouldCreateWebContents(
content::WebContents* web_contents,
int route_id,
int main_frame_route_id,
WindowContainerType window_container_type,
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) {
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillCreatePopupWindow(frame_name,
target_url,
partition_id,
NEW_FOREGROUND_TAB));
return false;
}
// In atom-shell all reloads and navigations started by renderer process would
// be redirected to this method, so we can have precise control of how we
// would open the url (in our case, is to restart the renderer process). See
// AtomRendererClient::ShouldFork for how this is done.
content::WebContents* NativeWindow::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) {
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillCreatePopupWindow(base::string16(),
params.url,
"",
params.disposition));
return nullptr;
}
// Give user a chance to prevent navigation.
bool prevent_default = false;
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillNavigate(&prevent_default, params.url));
if (prevent_default)
return nullptr;
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
}
void NativeWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
if (!transparent_)
@ -533,20 +495,8 @@ void NativeWindow::RenderViewCreated(
impl->SetBackgroundOpaque(false);
}
void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) {
*proceed_to_fire_unload = proceed;
}
void NativeWindow::MoveContents(content::WebContents* source,
const gfx::Rect& pos) {
SetBounds(pos);
}
void NativeWindow::CloseContents(content::WebContents* source) {
// Destroy the WebContents before we close the window.
DestroyWebContents();
inspectable_web_contents_ = nullptr;
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
@ -575,11 +525,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
}
void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
}
void NativeWindow::BeforeUnloadDialogCancelled() {
WindowList::WindowCloseCancelled(this);
@ -609,18 +554,6 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
return handled;
}
void NativeWindow::DevToolsFocused() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
}
void NativeWindow::DevToolsOpened() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
}
void NativeWindow::DevToolsClosed() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
}
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresposive_closure_.IsCancelled())
return;

View file

@ -9,7 +9,6 @@
#include <string>
#include <vector>
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h"
@ -17,17 +16,22 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/public/browser/readback_types.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "native_mate/persistent_dictionary.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
namespace base {
class CommandLine;
}
namespace brightray {
class InspectableWebContents;
}
namespace content {
class BrowserContext;
class WebContents;
struct NativeWebKeyboardEvent;
struct WebPreferences;
}
@ -49,8 +53,7 @@ namespace atom {
struct DraggableRegion;
class NativeWindow : public CommonWebContentsDelegate,
public content::WebContentsObserver {
class NativeWindow : public content::WebContentsObserver {
public:
typedef base::Callback<void(const SkBitmap& bitmap)> CapturePageCallback;
@ -167,6 +170,17 @@ class NativeWindow : public CommonWebContentsDelegate,
return weak_factory_.GetWeakPtr();
}
content::WebContents* GetWebContents() const;
// Methods called by the WebContents.
virtual void CloseContents(content::WebContents* source);
virtual void RendererUnresponsive(content::WebContents* source);
virtual void RendererResponsive(content::WebContents* source);
virtual void ActivateContents(content::WebContents* contents) {}
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {}
// Called when renderer process is going to be started.
void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
void OverrideWebkitPrefs(content::WebPreferences* prefs);
@ -214,40 +228,12 @@ class NativeWindow : public CommonWebContentsDelegate,
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0;
// Implementations of content::WebContentsDelegate.
bool ShouldCreateWebContents(
content::WebContents* web_contents,
int route_id,
int main_frame_route_id,
WindowContainerType window_container_type,
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) override;
void MoveContents(content::WebContents* source,
const gfx::Rect& pos) override;
void CloseContents(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
// Implementations of content::WebContentsObserver.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
void BeforeUnloadDialogCancelled() override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
bool OnMessageReceived(const IPC::Message& message) override;
// Implementations of brightray::InspectableWebContentsDelegate.
void DevToolsFocused() override;
void DevToolsOpened() override;
void DevToolsClosed() override;
// Whether window has standard frame.
bool has_frame_;

View file

@ -27,7 +27,7 @@ class NativeWindowMac : public NativeWindow {
const mate::Dictionary& options);
~NativeWindowMac() override;
// NativeWindow implementation.
// NativeWindow:
void Close() override;
void CloseImmediately() override;
void Focus(bool focus) override;
@ -91,7 +91,7 @@ class NativeWindowMac : public NativeWindow {
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
// Implementations of content::WebContentsDelegate.
// NativeWindow:
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent&) override;

View file

@ -386,9 +386,7 @@ NativeWindowMac::NativeWindowMac(
}
NativeWindowMac::~NativeWindowMac() {
// Force InspectableWebContents to be destroyed before we destroy window,
// because it may still be observing the window at this time.
DestroyWebContents();
Observe(nullptr);
}
void NativeWindowMac::Close() {

View file

@ -127,7 +127,7 @@ class NativeWindowViews : public NativeWindow,
std::string* name, std::string* class_name) override;
#endif
// content::WebContentsDelegate:
// NativeWindow:
void ActivateContents(content::WebContents* contents) override;
void HandleKeyboardEvent(
content::WebContents*,