Merge pull request #2051 from atom/detach-web-contents

Decouple WebContents from NativeWindow
This commit is contained in:
Cheng Zhao 2015-06-25 15:11:40 +08:00
commit 1418fdbc02
25 changed files with 694 additions and 659 deletions

View file

@ -22,7 +22,7 @@ void MenuMac::Popup(Window* window) {
NativeWindow* native_window = window->window(); NativeWindow* native_window = window->window();
if (!native_window) if (!native_window)
return; return;
content::WebContents* web_contents = native_window->GetWebContents(); content::WebContents* web_contents = native_window->web_contents();
if (!web_contents) if (!web_contents)
return; return;
@ -54,7 +54,7 @@ void MenuMac::PopupAt(Window* window, int x, int y) {
NativeWindow* native_window = window->window(); NativeWindow* native_window = window->window();
if (!native_window) if (!native_window)
return; return;
content::WebContents* web_contents = native_window->GetWebContents(); content::WebContents* web_contents = native_window->web_contents();
if (!web_contents) if (!web_contents)
return; return;

View file

@ -24,7 +24,7 @@ void MenuViews::PopupAt(Window* window, int x, int y) {
NativeWindow* native_window = static_cast<NativeWindow*>(window->window()); NativeWindow* native_window = static_cast<NativeWindow*>(window->window());
if (!native_window) if (!native_window)
return; return;
content::WebContents* web_contents = native_window->GetWebContents(); content::WebContents* web_contents = native_window->web_contents();
if (!web_contents) if (!web_contents)
return; return;
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView(); content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();

View file

@ -11,6 +11,7 @@
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/web_view_guest_delegate.h"
#include "atom/common/api/api_messages.h" #include "atom/common/api/api_messages.h"
#include "atom/common/event_emitter_caller.h" #include "atom/common/event_emitter_caller.h"
#include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h"
@ -24,14 +25,12 @@
#include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/printing/print_preview_message_handler.h" #include "chrome/browser/printing/print_preview_message_handler.h"
#include "content/public/browser/favicon_status.h" #include "content/public/browser/favicon_status.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/plugin_service.h" #include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_request_details.h" #include "content/public/browser/resource_request_details.h"
#include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
@ -57,10 +56,10 @@ struct PrintSettings {
namespace mate { namespace mate {
template<> template<>
struct Converter<atom::api::SetSizeParams> { struct Converter<atom::SetSizeParams> {
static bool FromV8(v8::Isolate* isolate, static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val, v8::Local<v8::Value> val,
atom::api::SetSizeParams* out) { atom::SetSizeParams* out) {
mate::Dictionary params; mate::Dictionary params;
if (!ConvertFromV8(isolate, val, &params)) if (!ConvertFromV8(isolate, val, &params))
return false; return false;
@ -116,9 +115,6 @@ namespace api {
namespace { namespace {
const int kDefaultWidth = 300;
const int kDefaultHeight = 300;
v8::Persistent<v8::ObjectTemplate> template_; v8::Persistent<v8::ObjectTemplate> template_;
// The wrapWebContents funtion which is implemented in JavaScript // The wrapWebContents funtion which is implemented in JavaScript
@ -142,46 +138,50 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
} // namespace } // namespace
WebContents::WebContents(brightray::InspectableWebContents* web_contents)
: WebContents(web_contents->GetWebContents()) {
inspectable_web_contents_ = web_contents;
}
WebContents::WebContents(content::WebContents* web_contents) WebContents::WebContents(content::WebContents* web_contents)
: CommonWebContentsDelegate(false), : content::WebContentsObserver(web_contents),
content::WebContentsObserver(web_contents), type_(REMOTE) {
guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false),
is_full_page_plugin_(false),
inspectable_web_contents_(nullptr) {
AttachAsUserData(web_contents); AttachAsUserData(web_contents);
} }
WebContents::WebContents(const mate::Dictionary& options) WebContents::WebContents(const mate::Dictionary& options) {
: CommonWebContentsDelegate(true), bool is_guest = false;
guest_opaque_(true), options.Get("isGuest", &is_guest);
guest_host_(nullptr),
auto_size_enabled_(false), type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
is_full_page_plugin_(false) {
auto browser_context = AtomBrowserMainParts::Get()->browser_context(); auto browser_context = AtomBrowserMainParts::Get()->browser_context();
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL( content::WebContents* web_contents;
browser_context, GURL("chrome-guest://fake-host")); if (is_guest) {
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
content::WebContents::CreateParams params(browser_context, site_instance); browser_context, GURL("chrome-guest://fake-host"));
params.guest_delegate = this; content::WebContents::CreateParams params(browser_context, site_instance);
auto web_contents = content::WebContents::Create(params); guest_delegate_.reset(new WebViewGuestDelegate);
params.guest_delegate = guest_delegate_.get();
NativeWindow* owner_window = nullptr; web_contents = content::WebContents::Create(params);
WebContents* embedder = nullptr; } else {
if (options.Get("embedder", &embedder) && embedder) content::WebContents::CreateParams params(browser_context);
owner_window = NativeWindow::FromWebContents(embedder->web_contents()); web_contents = content::WebContents::Create(params);
}
Observe(web_contents);
AttachAsUserData(web_contents); AttachAsUserData(web_contents);
InitWithWebContents(web_contents, owner_window); InitWithWebContents(web_contents);
inspectable_web_contents_ = managed_web_contents();
Observe(GetWebContents()); if (is_guest) {
guest_delegate_->Initialize(this);
NativeWindow* owner_window = nullptr;
WebContents* embedder = nullptr;
if (options.Get("embedder", &embedder) && embedder) {
// New WebContents's owner_window is the embedder's owner_window.
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
if (relay)
owner_window = relay->window.get();
}
if (owner_window)
SetOwnerWindow(owner_window);
}
} }
WebContents::~WebContents() { WebContents::~WebContents() {
@ -193,8 +193,12 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
const base::string16& message, const base::string16& message,
int32 line_no, int32 line_no,
const base::string16& source_id) { const base::string16& source_id) {
Emit("console-message", level, message, line_no, source_id); if (type_ == BROWSER_WINDOW) {
return true; return false;
} else {
Emit("console-message", level, message, line_no, source_id);
return true;
}
} }
bool WebContents::ShouldCreateWebContents( bool WebContents::ShouldCreateWebContents(
@ -206,19 +210,21 @@ bool WebContents::ShouldCreateWebContents(
const GURL& target_url, const GURL& target_url,
const std::string& partition_id, const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) { 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; return false;
} }
void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
}
content::WebContents* WebContents::OpenURLFromTab( content::WebContents* WebContents::OpenURLFromTab(
content::WebContents* source, content::WebContents* source,
const content::OpenURLParams& params) { const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) { 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; return nullptr;
} }
@ -229,15 +235,43 @@ content::WebContents* WebContents::OpenURLFromTab(
return CommonWebContentsDelegate::OpenURLFromTab(source, params); 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) {
Emit("activate");
}
bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
return type_ == BROWSER_WINDOW;
}
void WebContents::HandleKeyboardEvent( void WebContents::HandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event) { const content::NativeWebKeyboardEvent& event) {
if (!attached()) if (type_ == BROWSER_WINDOW) {
return; owner_window()->HandleKeyboardEvent(source, event);
} else if (type_ == WEB_VIEW && guest_delegate_) {
// Send the unhandled keyboard events back to the embedder to reprocess them. // Send the unhandled keyboard events back to the embedder.
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent( guest_delegate_->HandleKeyboardEvent(source, event);
web_contents(), event); }
} }
void WebContents::EnterFullscreenModeForTab(content::WebContents* source, void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
@ -251,6 +285,23 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
Emit("leave-html-full-screen"); 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) { void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
int process_id = render_view_host->GetProcess()->GetID(); int process_id = render_view_host->GetProcess()->GetID();
Emit("render-view-deleted", process_id); Emit("render-view-deleted", process_id);
@ -405,21 +456,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
return handled; return handled;
} }
void WebContents::RenderViewReady() {
if (!is_guest())
return;
// We don't want to accidentally set the opacity of an interstitial page.
// WebContents::GetRenderWidgetHostView will return the RWHV of an
// interstitial page if one is showing at this time. We only want opacity
// to apply to web pages.
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
if (guest_opaque_)
render_view_host_view->SetBackgroundColorToDefault();
else
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
}
void WebContents::WebContentsDestroyed() { void WebContents::WebContentsDestroyed() {
// The RenderViewDeleted was not called when the WebContents is destroyed. // The RenderViewDeleted was not called when the WebContents is destroyed.
RenderViewDeleted(web_contents()->GetRenderViewHost()); RenderViewDeleted(web_contents()->GetRenderViewHost());
@ -433,40 +469,12 @@ void WebContents::NavigationEntryCommitted(
details.is_in_page, details.did_replace_entry); details.is_in_page, details.did_replace_entry);
} }
void WebContents::DidAttach(int guest_proxy_routing_id) {
Emit("did-attach");
}
content::WebContents* WebContents::GetOwnerWebContents() const {
return embedder_web_contents_;
}
void WebContents::GuestSizeChanged(const gfx::Size& new_size) {
if (!auto_size_enabled_)
return;
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
guest_size_ = new_size;
}
void WebContents::SetGuestHost(content::GuestHost* guest_host) {
guest_host_ = guest_host;
}
void WebContents::WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) {
embedder_web_contents_ = embedder_web_contents;
is_full_page_plugin_ = is_full_page_plugin;
}
void WebContents::Destroy() { void WebContents::Destroy() {
if (is_guest() && managed_web_contents()) { if (type_ == WEB_VIEW && managed_web_contents()) {
// When force destroying the "destroyed" event is not emitted. // When force destroying the "destroyed" event is not emitted.
WebContentsDestroyed(); WebContentsDestroyed();
// Give the content module an opportunity to perform some cleanup. guest_delegate_->Destroy();
guest_host_->WillDestroy();
guest_host_ = nullptr;
Observe(nullptr); Observe(nullptr);
DestroyWebContents(); DestroyWebContents();
@ -555,29 +563,32 @@ void WebContents::ExecuteJavaScript(const base::string16& code) {
} }
void WebContents::OpenDevTools(mate::Arguments* args) { void WebContents::OpenDevTools(mate::Arguments* args) {
if (!inspectable_web_contents()) if (type_ == REMOTE)
return; return;
bool detach = false; bool detach = false;
if (is_guest()) { if (type_ == WEB_VIEW) {
detach = true; detach = true;
} else if (args && args->Length() == 1) { } else if (args && args->Length() == 1) {
mate::Dictionary options; mate::Dictionary options;
args->GetNext(&options) && options.Get("detach", &detach); args->GetNext(&options) && options.Get("detach", &detach);
} }
inspectable_web_contents()->SetCanDock(!detach); managed_web_contents()->SetCanDock(!detach);
inspectable_web_contents()->ShowDevTools(); managed_web_contents()->ShowDevTools();
} }
void WebContents::CloseDevTools() { void WebContents::CloseDevTools() {
if (!inspectable_web_contents()) if (type_ == REMOTE)
return; return;
inspectable_web_contents()->CloseDevTools();
managed_web_contents()->CloseDevTools();
} }
bool WebContents::IsDevToolsOpened() { bool WebContents::IsDevToolsOpened() {
if (!inspectable_web_contents()) if (type_ == REMOTE)
return false; return false;
return inspectable_web_contents()->IsDevToolsViewShowing();
return managed_web_contents()->IsDevToolsViewShowing();
} }
void WebContents::ToggleDevTools() { void WebContents::ToggleDevTools() {
@ -588,8 +599,9 @@ void WebContents::ToggleDevTools() {
} }
void WebContents::InspectElement(int x, int y) { void WebContents::InspectElement(int x, int y) {
if (!inspectable_web_contents()) if (type_ == REMOTE)
return; return;
OpenDevTools(nullptr); OpenDevTools(nullptr);
scoped_refptr<content::DevToolsAgentHost> agent( scoped_refptr<content::DevToolsAgentHost> agent(
content::DevToolsAgentHost::GetOrCreateFor(web_contents())); content::DevToolsAgentHost::GetOrCreateFor(web_contents()));
@ -597,13 +609,14 @@ void WebContents::InspectElement(int x, int y) {
} }
void WebContents::InspectServiceWorker() { void WebContents::InspectServiceWorker() {
if (!inspectable_web_contents()) if (type_ == REMOTE)
return; return;
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) { for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() == if (agent_host->GetType() ==
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) { content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
OpenDevTools(nullptr); OpenDevTools(nullptr);
inspectable_web_contents()->AttachTo(agent_host); managed_web_contents()->AttachTo(agent_host);
break; break;
} }
} }
@ -715,76 +728,17 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
} }
void WebContents::SetSize(const SetSizeParams& params) { void WebContents::SetSize(const SetSizeParams& params) {
bool enable_auto_size = if (guest_delegate_)
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_; guest_delegate_->SetSize(params);
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
if (params.normal_size)
normal_size_ = *params.normal_size;
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
if (enable_auto_size) {
// Autosize is being enabled.
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
normal_size_.SetSize(0, 0);
} else {
// Autosize is being disabled.
// Use default width/height if missing from partially defined normal size.
if (normal_size_.width() && !normal_size_.height())
normal_size_.set_height(GetDefaultSize().height());
if (!normal_size_.width() && normal_size_.height())
normal_size_.set_width(GetDefaultSize().width());
gfx::Size new_size;
if (!normal_size_.IsEmpty()) {
new_size = normal_size_;
} else if (!guest_size_.IsEmpty()) {
new_size = guest_size_;
} else {
new_size = GetDefaultSize();
}
if (auto_size_enabled_) {
// Autosize was previously enabled.
rvh->DisableAutoResize(new_size);
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
} else {
// Autosize was already disabled.
guest_host_->SizeContents(new_size);
}
guest_size_ = new_size;
}
auto_size_enabled_ = enable_auto_size;
} }
void WebContents::SetAllowTransparency(bool allow) { void WebContents::SetAllowTransparency(bool allow) {
if (guest_opaque_ != allow) if (guest_delegate_)
return; guest_delegate_->SetAllowTransparency(allow);
auto render_view_host = web_contents()->GetRenderViewHost();
guest_opaque_ = !allow;
if (!render_view_host->GetView())
return;
if (guest_opaque_) {
render_view_host->GetView()->SetBackgroundColorToDefault();
} else {
render_view_host->GetView()->SetBackgroundColor(SK_ColorTRANSPARENT);
}
} }
bool WebContents::IsGuest() const { bool WebContents::IsGuest() const {
return is_guest(); return type_ == WEB_VIEW;
} }
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
@ -856,38 +810,6 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args); EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args);
} }
void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) {
Emit("size-changed",
old_size.width(), old_size.height(),
new_size.width(), new_size.height());
}
gfx::Size WebContents::GetDefaultSize() const {
if (is_full_page_plugin_) {
// Full page plugins default to the size of the owner's viewport.
return embedder_web_contents_->GetRenderWidgetHostView()
->GetVisibleViewportSize();
} else {
return gfx::Size(kDefaultWidth, kDefaultHeight);
}
}
// 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 // static
mate::Handle<WebContents> WebContents::CreateFrom( mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) { v8::Isolate* isolate, content::WebContents* web_contents) {

View file

@ -10,7 +10,6 @@
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/common_web_contents_delegate.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/common/favicon_url.h" #include "content/public/common/favicon_url.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/gpu_data_manager_observer.h" #include "content/public/browser/gpu_data_manager_observer.h"
@ -28,26 +27,12 @@ class Dictionary;
namespace atom { namespace atom {
struct SetSizeParams;
class WebViewGuestDelegate;
namespace api { namespace api {
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams() {}
~SetSizeParams() {}
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
class WebContents : public mate::TrackableObject<WebContents>, class WebContents : public mate::TrackableObject<WebContents>,
public content::BrowserPluginGuestDelegate,
public CommonWebContentsDelegate, public CommonWebContentsDelegate,
public content::WebContentsObserver, public content::WebContentsObserver,
public content::GpuDataManagerObserver { public content::GpuDataManagerObserver {
@ -57,8 +42,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
PrintToPDFCallback; PrintToPDFCallback;
// Create from an existing WebContents. // Create from an existing WebContents.
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
static mate::Handle<WebContents> CreateFrom( static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents); v8::Isolate* isolate, content::WebContents* web_contents);
@ -117,26 +100,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
bool SendIPCMessage(const base::string16& channel, bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
// Used to toggle autosize mode for this GuestView, and set both the automatic // Methods for creating <webview>.
// and normal sizes.
void SetSize(const SetSizeParams& params); void SetSize(const SetSizeParams& params);
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow); void SetAllowTransparency(bool allow);
bool IsGuest() const; bool IsGuest() const;
// Returns whether this guest has an associated embedder.
bool attached() const { return !!embedder_web_contents_; }
// Returns the current InspectableWebContents object, nullptr will be returned
// if current WebContents can not beinspected, e.g. it is the devtools.
brightray::InspectableWebContents* inspectable_web_contents() const {
return inspectable_web_contents_;
}
protected: protected:
explicit WebContents(brightray::InspectableWebContents* web_contents);
explicit WebContents(content::WebContents* web_contents); explicit WebContents(content::WebContents* web_contents);
explicit WebContents(const mate::Dictionary& options); explicit WebContents(const mate::Dictionary& options);
~WebContents(); ~WebContents();
@ -160,18 +129,28 @@ class WebContents : public mate::TrackableObject<WebContents>,
const GURL& target_url, const GURL& target_url,
const std::string& partition_id, const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) override; content::SessionStorageNamespace* session_storage_namespace) override;
void CloseContents(content::WebContents* source) override;
content::WebContents* OpenURLFromTab( content::WebContents* OpenURLFromTab(
content::WebContents* source, content::WebContents* source,
const content::OpenURLParams& params) override; 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( void HandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override; const content::NativeWebKeyboardEvent& event) override;
void EnterFullscreenModeForTab(content::WebContents* source, void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override; const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override; void ExitFullscreenModeForTab(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
// content::WebContentsObserver: // content::WebContentsObserver:
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
void RenderViewDeleted(content::RenderViewHost*) override; void RenderViewDeleted(content::RenderViewHost*) override;
void RenderProcessGone(base::TerminationStatus status) override; void RenderProcessGone(base::TerminationStatus status) override;
void DocumentLoadedInFrame( void DocumentLoadedInFrame(
@ -197,7 +176,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
const content::LoadCommittedDetails& details, const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override; const content::FrameNavigateParams& params) override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
void RenderViewReady() override;
void WebContentsDestroyed() override; void WebContentsDestroyed() override;
void NavigationEntryCommitted( void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override; const content::LoadCommittedDetails& load_details) override;
@ -207,19 +185,16 @@ class WebContents : public mate::TrackableObject<WebContents>,
void PluginCrashed(const base::FilePath& plugin_path, void PluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) override; base::ProcessId plugin_pid) override;
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) final;
// content::GpuDataManagerObserver: // content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override; void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
private: private:
enum Type {
BROWSER_WINDOW, // Used by BrowserWindow.
WEB_VIEW, // Used by <webview>.
REMOTE, // Thin wrap around an existing WebContents.
};
// Called when received a message from renderer. // Called when received a message from renderer.
void OnRendererMessage(const base::string16& channel, void OnRendererMessage(const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
@ -229,53 +204,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
const base::ListValue& args, const base::ListValue& args,
IPC::Message* message); IPC::Message* message);
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
v8::Global<v8::Value> session_; v8::Global<v8::Value> session_;
// Stores whether the contents of the guest can be transparent. scoped_ptr<WebViewGuestDelegate> guest_delegate_;
bool guest_opaque_;
// The WebContents that attaches this guest view. // The type of current WebContents.
content::WebContents* embedder_web_contents_; Type type_;
// The size of the container element.
gfx::Size element_size_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// A pointer to the guest_host.
content::GuestHost* guest_host_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
// Current InspectableWebContents object, can be nullptr for WebContents of
// devtools. It is a weak reference.
brightray::InspectableWebContents* inspectable_web_contents_;
DISALLOW_COPY_AND_ASSIGN(WebContents); DISALLOW_COPY_AND_ASSIGN(WebContents);
}; };

View file

@ -38,8 +38,17 @@ void OnCapturePageDone(
} // namespace } // namespace
Window::Window(const mate::Dictionary& options) Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
: window_(NativeWindow::Create(options)) { // Creates the WebContents used by BrowserWindow.
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(),
options));
web_contents->SetOwnerWindow(window_.get());
window_->InitFromOptions(options); window_->InitFromOptions(options);
window_->AddObserver(this); window_->AddObserver(this);
} }
@ -49,29 +58,11 @@ Window::~Window() {
Destroy(); Destroy();
} }
void Window::AfterInit(v8::Isolate* isolate) {
mate::TrackableObject<Window>::AfterInit(isolate);
auto web_contents = window_->managed_web_contents();
auto handle = WebContents::CreateFrom(isolate, web_contents);
web_contents_.Reset(isolate, handle.ToV8());
}
void Window::OnPageTitleUpdated(bool* prevent_default, void Window::OnPageTitleUpdated(bool* prevent_default,
const std::string& title) { const std::string& title) {
*prevent_default = Emit("page-title-updated", title); *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) { void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close"); *prevent_default = Emit("close");
} }
@ -79,6 +70,12 @@ void Window::WillCloseWindow(bool* prevent_default) {
void Window::OnWindowClosed() { void Window::OnWindowClosed() {
Emit("closed"); Emit("closed");
if (api_web_contents_) {
api_web_contents_->DestroyWebContents();
api_web_contents_ = nullptr;
web_contents_.Reset();
}
RemoveFromWeakMap(); RemoveFromWeakMap();
window_->RemoveObserver(this); window_->RemoveObserver(this);
} }
@ -152,8 +149,8 @@ void Window::OnDevToolsOpened() {
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
auto handle = WebContents::CreateFrom(isolate(), auto handle = WebContents::CreateFrom(
window_->GetDevToolsWebContents()); isolate(), api_web_contents_->GetDevToolsWebContents());
devtools_web_contents_.Reset(isolate(), handle.ToV8()); devtools_web_contents_.Reset(isolate(), handle.ToV8());
} }
@ -173,12 +170,11 @@ mate::Wrappable* Window::New(v8::Isolate* isolate,
"Cannot create BrowserWindow before app is ready"); "Cannot create BrowserWindow before app is ready");
return nullptr; return nullptr;
} }
return new Window(options); return new Window(isolate, options);
} }
void Window::Destroy() { void Window::Destroy() {
window_->DestroyWebContents(); window_->CloseContents(nullptr);
window_->CloseImmediately();
} }
void Window::Close() { void Window::Close() {

View file

@ -45,20 +45,12 @@ class Window : public mate::TrackableObject<Window>,
NativeWindow* window() const { return window_.get(); } NativeWindow* window() const { return window_.get(); }
protected: protected:
explicit Window(const mate::Dictionary& options); Window(v8::Isolate* isolate, const mate::Dictionary& options);
virtual ~Window(); virtual ~Window();
// mate::Wrappable:
void AfterInit(v8::Isolate* isolate) override;
// NativeWindowObserver: // NativeWindowObserver:
void OnPageTitleUpdated(bool* prevent_default, void OnPageTitleUpdated(bool* prevent_default,
const std::string& title) override; 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 WillCloseWindow(bool* prevent_default) override;
void OnWindowClosed() override; void OnWindowClosed() override;
void OnWindowBlur() override; void OnWindowBlur() override;
@ -154,6 +146,8 @@ class Window : public mate::TrackableObject<Window>,
v8::Global<v8::Value> devtools_web_contents_; v8::Global<v8::Value> devtools_web_contents_;
v8::Global<v8::Value> menu_; v8::Global<v8::Value> menu_;
api::WebContents* api_web_contents_;
scoped_ptr<NativeWindow> window_; scoped_ptr<NativeWindow> window_;
DISALLOW_COPY_AND_ASSIGN(Window); DISALLOW_COPY_AND_ASSIGN(Window);

View file

@ -6,6 +6,7 @@
#include "atom/browser/api/event.h" #include "atom/browser/api/event.h"
#include "native_mate/arguments.h" #include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h" #include "native_mate/object_template_builder.h"
namespace mate { namespace mate {
@ -15,8 +16,8 @@ namespace {
v8::Persistent<v8::ObjectTemplate> event_template; v8::Persistent<v8::ObjectTemplate> event_template;
void PreventDefault(mate::Arguments* args) { void PreventDefault(mate::Arguments* args) {
args->GetThis()->Set(StringToV8(args->isolate(), "defaultPrevented"), mate::Dictionary self(args->isolate(), args->GetThis());
v8::True(args->isolate())); self.Set("defaultPrevented", true);
} }
// Create a pure JavaScript Event object. // Create a pure JavaScript Event object.
@ -38,7 +39,7 @@ EventEmitter::EventEmitter() {
v8::Local<v8::Object> EventEmitter::CreateEvent(v8::Isolate* isolate, v8::Local<v8::Object> EventEmitter::CreateEvent(v8::Isolate* isolate,
content::WebContents* sender, content::WebContents* sender,
IPC::Message* message) const { IPC::Message* message) {
v8::Local<v8::Object> event; v8::Local<v8::Object> event;
bool use_native_event = sender && message; bool use_native_event = sender && message;
@ -49,6 +50,7 @@ v8::Local<v8::Object> EventEmitter::CreateEvent(v8::Isolate* isolate,
} else { } else {
event = CreateEventObject(isolate); event = CreateEventObject(isolate);
} }
mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
return event; return event;
} }

View file

@ -25,9 +25,6 @@ class EventEmitter : public Wrappable {
public: public:
typedef std::vector<v8::Local<v8::Value>> ValueArray; typedef std::vector<v8::Local<v8::Value>> ValueArray;
protected:
EventEmitter();
// this.emit(name, new Event(), args...); // this.emit(name, new Event(), args...);
template<typename... Args> template<typename... Args>
bool Emit(const base::StringPiece& name, const Args&... args) { bool Emit(const base::StringPiece& name, const Args&... args) {
@ -48,10 +45,13 @@ class EventEmitter : public Wrappable {
StringToV8(isolate(), "defaultPrevented"))->BooleanValue(); StringToV8(isolate(), "defaultPrevented"))->BooleanValue();
} }
protected:
EventEmitter();
private: private:
v8::Local<v8::Object> CreateEvent(v8::Isolate* isolate, v8::Local<v8::Object> CreateEvent(v8::Isolate* isolate,
content::WebContents* sender, content::WebContents* sender,
IPC::Message* message) const; IPC::Message* message);
DISALLOW_COPY_AND_ASSIGN(EventEmitter); DISALLOW_COPY_AND_ASSIGN(EventEmitter);
}; };

View file

@ -12,14 +12,18 @@ BrowserWindow::_init = ->
@setMenu menu if menu? @setMenu menu if menu?
# Make new windows requested by links behave like "window.open" # Make new windows requested by links behave like "window.open"
@on '-new-window', (event, url, frameName) => @webContents.on '-new-window', (event, url, frameName) ->
event.sender = @webContents
options = show: true, width: 800, height: 600 options = show: true, width: 800, height: 600
ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
# Redirect "will-navigate" to webContents. # window.move(...)
@on '-will-navigate', (event, url) => @webContents.on 'move', (event, size) =>
@webContents.emit 'will-navigate', event, url @setSize size
# Hide the auto-hide menu when webContents is focused.
@webContents.on 'activate', =>
if process.platform isnt 'darwin' and @isMenuBarAutoHide() and @isMenuBarVisible()
@setMenuBarVisibility false
# Redirect focus/blur event to app instance too. # Redirect focus/blur event to app instance too.
@on 'blur', (event) => @on 'blur', (event) =>

View file

@ -33,12 +33,10 @@ wrapWebContents = (webContents) ->
# Dispatch IPC messages to the ipc module. # Dispatch IPC messages to the ipc module.
webContents.on 'ipc-message', (event, packed) -> webContents.on 'ipc-message', (event, packed) ->
[channel, args...] = packed [channel, args...] = packed
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args... ipc.emit channel, event, args...
webContents.on 'ipc-message-sync', (event, packed) -> webContents.on 'ipc-message-sync', (event, packed) ->
[channel, args...] = packed [channel, args...] = packed
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args... ipc.emit channel, event, args...
webContents.printToPDF = (options, callback) -> webContents.printToPDF = (options, callback) ->

View file

@ -63,7 +63,7 @@ ProcessOwner GetProcessOwner(int process_id,
// First search for NativeWindow. // First search for NativeWindow.
for (auto native_window : *WindowList::GetInstance()) for (auto native_window : *WindowList::GetInstance())
if (web_contents == native_window->GetWebContents()) { if (web_contents == native_window->web_contents()) {
*window = native_window; *window = native_window;
return OWNER_NATIVE_WINDOW; return OWNER_NATIVE_WINDOW;
} }

View file

@ -65,12 +65,15 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
if (!item) if (!item)
return; return;
NativeWindow* window = nullptr;
auto relay = NativeWindowRelay::FromWebContents(item->GetWebContents());
if (relay)
window = relay->window.get();
file_dialog::Filters filters; file_dialog::Filters filters;
base::FilePath path; base::FilePath path;
auto owner_window_ = NativeWindow::FromWebContents(item->GetWebContents()); if (!file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
if (!file_dialog::ShowSaveDialog( filters, &path)) {
owner_window_, item->GetURL().spec(),
default_path, filters, &path)) {
return; return;
} }

View file

@ -107,10 +107,8 @@ void AppendToFile(const base::FilePath& path,
} // namespace } // namespace
CommonWebContentsDelegate::CommonWebContentsDelegate(bool is_guest) CommonWebContentsDelegate::CommonWebContentsDelegate()
: is_guest_(is_guest), : html_fullscreen_(false),
owner_window_(nullptr),
html_fullscreen_(false),
native_fullscreen_(false) { native_fullscreen_(false) {
} }
@ -118,9 +116,7 @@ CommonWebContentsDelegate::~CommonWebContentsDelegate() {
} }
void CommonWebContentsDelegate::InitWithWebContents( void CommonWebContentsDelegate::InitWithWebContents(
content::WebContents* web_contents, content::WebContents* web_contents) {
NativeWindow* owner_window) {
owner_window_ = owner_window;
web_contents->SetDelegate(this); web_contents->SetDelegate(this);
printing::PrintViewManagerBasic::CreateForWebContents(web_contents); printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
@ -131,6 +127,13 @@ void CommonWebContentsDelegate::InitWithWebContents(
web_contents_->SetDelegate(this); web_contents_->SetDelegate(this);
} }
void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
content::WebContents* web_contents = GetWebContents();
owner_window_ = owner_window->GetWeakPtr();
NativeWindowRelay* relay = new NativeWindowRelay(owner_window_);
web_contents->SetUserData(relay->key, relay);
}
void CommonWebContentsDelegate::DestroyWebContents() { void CommonWebContentsDelegate::DestroyWebContents() {
web_contents_.reset(); web_contents_.reset();
} }
@ -177,11 +180,6 @@ bool CommonWebContentsDelegate::CanOverscrollContent() const {
return false; return false;
} }
bool CommonWebContentsDelegate::IsPopupOrPanel(
const content::WebContents* source) const {
return !is_guest_;
}
content::JavaScriptDialogManager* content::JavaScriptDialogManager*
CommonWebContentsDelegate::GetJavaScriptDialogManager( CommonWebContentsDelegate::GetJavaScriptDialogManager(
content::WebContents* source) { content::WebContents* source) {
@ -202,7 +200,7 @@ void CommonWebContentsDelegate::RunFileChooser(
content::WebContents* guest, content::WebContents* guest,
const content::FileChooserParams& params) { const content::FileChooserParams& params) {
if (!web_dialog_helper_) if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_)); web_dialog_helper_.reset(new WebDialogHelper(owner_window()));
web_dialog_helper_->RunFileChooser(guest, params); web_dialog_helper_->RunFileChooser(guest, params);
} }
@ -210,7 +208,7 @@ void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
int request_id, int request_id,
const base::FilePath& path) { const base::FilePath& path) {
if (!web_dialog_helper_) if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_)); web_dialog_helper_.reset(new WebDialogHelper(owner_window()));
web_dialog_helper_->EnumerateDirectory(guest, request_id, path); web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
} }
@ -246,7 +244,7 @@ void CommonWebContentsDelegate::DevToolsSaveToFile(
} else { } else {
file_dialog::Filters filters; file_dialog::Filters filters;
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url)); base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
if (!file_dialog::ShowSaveDialog(owner_window_, url, default_path, if (!file_dialog::ShowSaveDialog(owner_window(), url, default_path,
filters, &path)) { filters, &path)) {
base::StringValue url_value(url); base::StringValue url_value(url);
web_contents_->CallClientFunction( web_contents_->CallClientFunction(
@ -281,7 +279,7 @@ void CommonWebContentsDelegate::DevToolsAddFileSystem() {
base::FilePath default_path; base::FilePath default_path;
std::vector<base::FilePath> paths; std::vector<base::FilePath> paths;
int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY; int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY;
if (!file_dialog::ShowOpenDialog(owner_window_, "", default_path, if (!file_dialog::ShowOpenDialog(owner_window(), "", default_path,
filters, flag, &paths)) filters, flag, &paths))
return; return;

View file

@ -23,13 +23,15 @@ class CommonWebContentsDelegate
: public brightray::DefaultWebContentsDelegate, : public brightray::DefaultWebContentsDelegate,
public brightray::InspectableWebContentsDelegate { public brightray::InspectableWebContentsDelegate {
public: public:
explicit CommonWebContentsDelegate(bool is_guest); CommonWebContentsDelegate();
virtual ~CommonWebContentsDelegate(); virtual ~CommonWebContentsDelegate();
// Create a InspectableWebContents object and takes onwership of // Creates a InspectableWebContents object and takes onwership of
// |web_contents|. // |web_contents|.
void InitWithWebContents(content::WebContents* web_contents, void InitWithWebContents(content::WebContents* web_contents);
NativeWindow* owner_window);
// Set the window as owner window.
void SetOwnerWindow(NativeWindow* owner_window);
// Destroy the managed InspectableWebContents object. // Destroy the managed InspectableWebContents object.
void DestroyWebContents(); void DestroyWebContents();
@ -44,7 +46,7 @@ class CommonWebContentsDelegate
return web_contents_.get(); return web_contents_.get();
} }
bool is_guest() const { return is_guest_; } NativeWindow* owner_window() const { return owner_window_.get(); }
protected: protected:
// content::WebContentsDelegate: // content::WebContentsDelegate:
@ -55,7 +57,6 @@ class CommonWebContentsDelegate
bool user_gesture, bool user_gesture,
bool last_unlocked_by_target) override; bool last_unlocked_by_target) override;
bool CanOverscrollContent() const override; bool CanOverscrollContent() const override;
bool IsPopupOrPanel(const content::WebContents* source) const override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager( content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override; content::WebContents* source) override;
content::ColorChooser* OpenColorChooser( content::ColorChooser* OpenColorChooser(
@ -92,11 +93,8 @@ class CommonWebContentsDelegate
// Set fullscreen mode triggered by html api. // Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen); void SetHtmlApiFullscreen(bool enter_fullscreen);
// Whether this is guest WebContents or NativeWindow.
const bool is_guest_;
// The window that this WebContents belongs to. // The window that this WebContents belongs to.
NativeWindow* owner_window_; base::WeakPtr<NativeWindow> owner_window_;
// Whether window is fullscreened by HTML5 api. // Whether window is fullscreened by HTML5 api.
bool html_fullscreen_; bool html_fullscreen_;

View file

@ -38,7 +38,7 @@ createGuest = (embedder, params) ->
webViewManager ?= process.atomBinding 'web_view_manager' webViewManager ?= process.atomBinding 'web_view_manager'
id = getNextInstanceId embedder id = getNextInstanceId embedder
guest = webContents.create {embedder} guest = webContents.create {isGuest: true, embedder}
guestInstances[id] = {guest, embedder} guestInstances[id] = {guest, embedder}
# Destroy guest when the embedder is gone or navigated. # Destroy guest when the embedder is gone or navigated.

View file

@ -30,9 +30,6 @@
#include "brightray/browser/inspectable_web_contents_view.h" #include "brightray/browser/inspectable_web_contents_view.h"
#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/plugin_service.h" #include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
@ -59,6 +56,8 @@ using content::NavigationEntry;
using content::RenderWidgetHostView; using content::RenderWidgetHostView;
using content::RenderWidgetHost; using content::RenderWidgetHost;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
namespace atom { namespace atom {
namespace { namespace {
@ -84,10 +83,10 @@ std::string RemoveWhitespace(const std::string& str) {
} // namespace } // namespace
NativeWindow::NativeWindow(content::WebContents* web_contents, NativeWindow::NativeWindow(
const mate::Dictionary& options) brightray::InspectableWebContents* inspectable_web_contents,
: CommonWebContentsDelegate(false), const mate::Dictionary& options)
content::WebContentsObserver(web_contents), : content::WebContentsObserver(inspectable_web_contents->GetWebContents()),
has_frame_(true), has_frame_(true),
transparent_(false), transparent_(false),
enable_larger_than_screen_(false), enable_larger_than_screen_(false),
@ -95,8 +94,9 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
node_integration_(true), node_integration_(true),
has_dialog_attached_(false), has_dialog_attached_(false),
zoom_factor_(1.0), zoom_factor_(1.0),
inspectable_web_contents_(inspectable_web_contents),
weak_factory_(this) { weak_factory_(this) {
InitWithWebContents(web_contents, this); inspectable_web_contents->GetView()->SetDelegate(this);
options.Get(switches::kFrame, &has_frame_); options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_); options.Get(switches::kTransparent, &transparent_);
@ -138,12 +138,8 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
RemoveWhitespace(browser->GetName()).c_str(), RemoveWhitespace(browser->GetName()).c_str(),
browser->GetVersion().c_str(), browser->GetVersion().c_str(),
CHROME_VERSION_STRING); CHROME_VERSION_STRING);
web_contents->GetMutableRendererPrefs()->user_agent_override = web_contents()->GetMutableRendererPrefs()->user_agent_override =
content::BuildUserAgentFromProduct(product_name); content::BuildUserAgentFromProduct(product_name);
// Get notified of title updated message.
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
content::Source<content::WebContents>(web_contents));
} }
NativeWindow::~NativeWindow() { NativeWindow::~NativeWindow() {
@ -152,19 +148,12 @@ NativeWindow::~NativeWindow() {
NotifyWindowClosed(); NotifyWindowClosed();
} }
// static
NativeWindow* NativeWindow::Create(const mate::Dictionary& options) {
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
content::WebContents::CreateParams create_params(browser_context);
return Create(content::WebContents::Create(create_params), options);
}
// static // static
NativeWindow* NativeWindow::FromWebContents( NativeWindow* NativeWindow::FromWebContents(
content::WebContents* web_contents) { content::WebContents* web_contents) {
WindowList& window_list = *WindowList::GetInstance(); WindowList& window_list = *WindowList::GetInstance();
for (NativeWindow* window : window_list) { for (NativeWindow* window : window_list) {
if (window->GetWebContents() == web_contents) if (window->web_contents() == web_contents)
return window; return window;
} }
return nullptr; return nullptr;
@ -279,24 +268,22 @@ bool NativeWindow::HasModalDialog() {
} }
void NativeWindow::FocusOnWebView() { void NativeWindow::FocusOnWebView() {
GetWebContents()->GetRenderViewHost()->Focus(); web_contents()->GetRenderViewHost()->Focus();
} }
void NativeWindow::BlurWebView() { void NativeWindow::BlurWebView() {
GetWebContents()->GetRenderViewHost()->Blur(); web_contents()->GetRenderViewHost()->Blur();
} }
bool NativeWindow::IsWebViewFocused() { bool NativeWindow::IsWebViewFocused() {
RenderWidgetHostView* host_view = auto host_view = web_contents()->GetRenderViewHost()->GetView();
GetWebContents()->GetRenderViewHost()->GetView();
return host_view && host_view->HasFocus(); return host_view && host_view->HasFocus();
} }
void NativeWindow::CapturePage(const gfx::Rect& rect, void NativeWindow::CapturePage(const gfx::Rect& rect,
const CapturePageCallback& callback) { const CapturePageCallback& callback) {
content::WebContents* contents = GetWebContents(); const auto view = web_contents()->GetRenderWidgetHostView();
RenderWidgetHostView* const view = contents->GetRenderWidgetHostView(); const auto host = view ? view->GetRenderWidgetHost() : nullptr;
RenderWidgetHost* const host = view ? view->GetRenderWidgetHost() : nullptr;
if (!view || !host) { if (!view || !host) {
callback.Run(SkBitmap()); callback.Run(SkBitmap());
return; return;
@ -326,7 +313,7 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
kBGRA_8888_SkColorType); kBGRA_8888_SkColorType);
} }
void NativeWindow::CloseWebContents() { void NativeWindow::RequestToClosePage() {
bool prevent_default = false; bool prevent_default = false;
FOR_EACH_OBSERVER(NativeWindowObserver, FOR_EACH_OBSERVER(NativeWindowObserver,
observers_, observers_,
@ -336,12 +323,6 @@ void NativeWindow::CloseWebContents() {
return; return;
} }
content::WebContents* web_contents(GetWebContents());
if (!web_contents) {
CloseImmediately();
return;
}
// Assume the window is not responding if it doesn't cancel the close and is // Assume the window is not responding if it doesn't cancel the close and is
// not closed in 5s, in this way we can quickly show the unresponsive // not closed in 5s, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for // dialog when the window is busy executing some script withouth waiting for
@ -349,10 +330,45 @@ void NativeWindow::CloseWebContents() {
if (window_unresposive_closure_.IsCancelled()) if (window_unresposive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000); ScheduleUnresponsiveEvent(5000);
if (web_contents->NeedToFireBeforeUnload()) if (web_contents()->NeedToFireBeforeUnload())
web_contents->DispatchBeforeUnload(false); web_contents()->DispatchBeforeUnload(false);
else else
web_contents->Close(); web_contents()->Close();
}
void NativeWindow::CloseContents(content::WebContents* source) {
if (!inspectable_web_contents_)
return;
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
inspectable_web_contents_ = nullptr;
Observe(nullptr);
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresposive_closure_.Cancel();
}
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicity started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
void NativeWindow::RendererResponsive(content::WebContents* source) {
window_unresposive_closure_.Cancel();
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
} }
void NativeWindow::AppendExtraCommandLineSwitches( void NativeWindow::AppendExtraCommandLineSwitches(
@ -430,10 +446,6 @@ void NativeWindow::NotifyWindowClosed() {
is_closed_ = true; is_closed_ = true;
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowClosed()); FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowClosed());
// Do not receive any notification after window has been closed, there is a
// crash that seems to be caused by this: http://git.io/YqMG5g.
registrar_.RemoveAll();
WindowList::RemoveWindow(this); WindowList::RemoveWindow(this);
} }
@ -493,50 +505,16 @@ void NativeWindow::NotifyWindowLeaveHtmlFullScreen() {
OnWindowLeaveHtmlFullScreen()); OnWindowLeaveHtmlFullScreen());
} }
bool NativeWindow::ShouldCreateWebContents( void NativeWindow::DevToolsFocused() {
content::WebContents* web_contents, FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
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 void NativeWindow::DevToolsOpened() {
// be redirected to this method, so we can have precise control of how we FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
// 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. void NativeWindow::DevToolsClosed() {
bool prevent_default = false; FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillNavigate(&prevent_default, params.url));
if (prevent_default)
return nullptr;
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
} }
void NativeWindow::RenderViewCreated( void NativeWindow::RenderViewCreated(
@ -551,66 +529,22 @@ void NativeWindow::RenderViewCreated(
impl->SetBackgroundOpaque(false); impl->SetBackgroundOpaque(false);
} }
void NativeWindow::BeforeUnloadFired(content::WebContents* tab, void NativeWindow::BeforeUnloadDialogCancelled() {
bool proceed, WindowList::WindowCloseCancelled(this);
bool* proceed_to_fire_unload) {
*proceed_to_fire_unload = proceed;
if (!proceed) { // Cancel unresponsive event when window close is cancelled.
WindowList::WindowCloseCancelled(this);
// Cancel unresponsive event when window close is cancelled.
window_unresposive_closure_.Cancel();
}
}
void NativeWindow::ActivateContents(content::WebContents* contents) {
FocusOnWebView();
}
void NativeWindow::DeactivateContents(content::WebContents* contents) {
BlurWebView();
}
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();
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresposive_closure_.Cancel(); window_unresposive_closure_.Cancel();
} }
void NativeWindow::RendererUnresponsive(content::WebContents* source) { void NativeWindow::TitleWasSet(content::NavigationEntry* entry,
// Schedule the unresponsive shortly later, since we may receive the bool explicit_set) {
// responsive event soon. This could happen after the whole application had bool prevent_default = false;
// blocked for a while. std::string text = base::UTF16ToUTF8(entry->GetTitle());
// Also notice that when closing this event would be ignored because we have FOR_EACH_OBSERVER(NativeWindowObserver,
// explicity started a close timeout counter. This is on purpose because we observers_,
// don't want the unresponsive event to be sent too early when user is closing OnPageTitleUpdated(&prevent_default, text));
// the window. if (!prevent_default)
ScheduleUnresponsiveEvent(50); SetTitle(text);
}
void NativeWindow::RendererResponsive(content::WebContents* source) {
window_unresposive_closure_.Cancel();
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.
} }
bool NativeWindow::OnMessageReceived(const IPC::Message& message) { bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
@ -624,38 +558,6 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
return handled; return handled;
} }
void NativeWindow::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
std::pair<NavigationEntry*, bool>* title =
content::Details<std::pair<NavigationEntry*, bool>>(details).ptr();
if (title->first) {
bool prevent_default = false;
std::string text = base::UTF16ToUTF8(title->first->GetTitle());
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
OnPageTitleUpdated(&prevent_default, text));
if (!prevent_default)
SetTitle(text);
}
}
}
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) { void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresposive_closure_.IsCancelled()) if (!window_unresposive_closure_.IsCancelled())
return; return;

View file

@ -9,26 +9,30 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/native_window_observer.h" #include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h" #include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h" #include "base/cancelable_callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "content/public/browser/notification_registrar.h" #include "brightray/browser/inspectable_web_contents_view_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/readback_types.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 "native_mate/persistent_dictionary.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
namespace base { namespace base {
class CommandLine; class CommandLine;
} }
namespace brightray {
class InspectableWebContents;
}
namespace content { namespace content {
class BrowserContext; struct NativeWebKeyboardEvent;
class WebContents;
struct WebPreferences; struct WebPreferences;
} }
@ -50,9 +54,8 @@ namespace atom {
struct DraggableRegion; struct DraggableRegion;
class NativeWindow : public CommonWebContentsDelegate, class NativeWindow : public content::WebContentsObserver,
public content::WebContentsObserver, public brightray::InspectableWebContentsViewDelegate {
public content::NotificationObserver {
public: public:
typedef base::Callback<void(const SkBitmap& bitmap)> CapturePageCallback; typedef base::Callback<void(const SkBitmap& bitmap)> CapturePageCallback;
@ -79,12 +82,9 @@ class NativeWindow : public CommonWebContentsDelegate,
// Create window with existing WebContents, the caller is responsible for // Create window with existing WebContents, the caller is responsible for
// managing the window's live. // managing the window's live.
static NativeWindow* Create(content::WebContents* web_contents, static NativeWindow* Create(
const mate::Dictionary& options); brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options);
// Create window with new WebContents, the caller is responsible for
// managing the window's live.
static NativeWindow* Create(const mate::Dictionary& options);
// Find a window from its WebContents // Find a window from its WebContents
static NativeWindow* FromWebContents(content::WebContents* web_contents); static NativeWindow* FromWebContents(content::WebContents* web_contents);
@ -163,15 +163,21 @@ class NativeWindow : public CommonWebContentsDelegate,
virtual void SetMenuBarVisibility(bool visible); virtual void SetMenuBarVisibility(bool visible);
virtual bool IsMenuBarVisible(); virtual bool IsMenuBarVisible();
// The same with closing a tab in a real browser.
//
// Should be called by platform code when user want to close the window.
virtual void CloseWebContents();
base::WeakPtr<NativeWindow> GetWeakPtr() { base::WeakPtr<NativeWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
// Requests the WebContents to close, can be cancelled by the page.
virtual void RequestToClosePage();
// 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 HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {}
// Called when renderer process is going to be started. // Called when renderer process is going to be started.
void AppendExtraCommandLineSwitches(base::CommandLine* command_line); void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
void OverrideWebkitPrefs(content::WebPreferences* prefs); void OverrideWebkitPrefs(content::WebPreferences* prefs);
@ -202,7 +208,7 @@ class NativeWindow : public CommonWebContentsDelegate,
} }
brightray::InspectableWebContents* inspectable_web_contents() const { brightray::InspectableWebContents* inspectable_web_contents() const {
return managed_web_contents(); return inspectable_web_contents_;
} }
bool has_frame() const { return has_frame_; } bool has_frame() const { return has_frame_; }
@ -212,52 +218,24 @@ class NativeWindow : public CommonWebContentsDelegate,
} }
protected: protected:
explicit NativeWindow(content::WebContents* web_contents, NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options); const mate::Dictionary& options);
// Called when the window needs to update its draggable region. // Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions( virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0; const std::vector<DraggableRegion>& regions) = 0;
// Implementations of content::WebContentsDelegate. // brightray::InspectableWebContentsViewDelegate:
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 ActivateContents(content::WebContents* contents) override;
void DeactivateContents(content::WebContents* contents) 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;
bool OnMessageReceived(const IPC::Message& message) override;
// Implementations of content::NotificationObserver.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Implementations of brightray::InspectableWebContentsDelegate.
void DevToolsFocused() override; void DevToolsFocused() override;
void DevToolsOpened() override; void DevToolsOpened() override;
void DevToolsClosed() override; void DevToolsClosed() override;
// content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadDialogCancelled() override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
bool OnMessageReceived(const IPC::Message& message) override;
// Whether window has standard frame. // Whether window has standard frame.
bool has_frame_; bool has_frame_;
@ -282,9 +260,6 @@ class NativeWindow : public CommonWebContentsDelegate,
const SkBitmap& bitmap, const SkBitmap& bitmap,
content::ReadbackResponse response); content::ReadbackResponse response);
// Notification manager.
content::NotificationRegistrar registrar_;
// Observers of this window. // Observers of this window.
ObserverList<NativeWindowObserver> observers_; ObserverList<NativeWindowObserver> observers_;
@ -310,11 +285,29 @@ class NativeWindow : public CommonWebContentsDelegate,
// Page's default zoom factor. // Page's default zoom factor.
double zoom_factor_; double zoom_factor_;
// The page this window is viewing.
brightray::InspectableWebContents* inspectable_web_contents_;
base::WeakPtrFactory<NativeWindow> weak_factory_; base::WeakPtrFactory<NativeWindow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NativeWindow); DISALLOW_COPY_AND_ASSIGN(NativeWindow);
}; };
// This class provides a hook to get a NativeWindow from a WebContents.
class NativeWindowRelay :
public content::WebContentsUserData<NativeWindowRelay> {
public:
explicit NativeWindowRelay(base::WeakPtr<NativeWindow> window)
: key(UserDataKey()), window(window) {}
void* key;
base::WeakPtr<NativeWindow> window;
private:
friend class content::WebContentsUserData<NativeWindow>;
};
} // namespace atom } // namespace atom
#endif // ATOM_BROWSER_NATIVE_WINDOW_H_ #endif // ATOM_BROWSER_NATIVE_WINDOW_H_

View file

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

View file

@ -68,7 +68,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
} }
- (void)windowDidBecomeMain:(NSNotification*)notification { - (void)windowDidBecomeMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->GetWebContents(); content::WebContents* web_contents = shell_->web_contents();
if (!web_contents) if (!web_contents)
return; return;
@ -82,7 +82,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
} }
- (void)windowDidResignMain:(NSNotification*)notification { - (void)windowDidResignMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->GetWebContents(); content::WebContents* web_contents = shell_->web_contents();
if (!web_contents) if (!web_contents)
return; return;
@ -149,7 +149,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
// When user tries to close the window by clicking the close button, we do // When user tries to close the window by clicking the close button, we do
// not close the window immediately, instead we try to close the web page // not close the window immediately, instead we try to close the web page
// fisrt, and when the web page is closed the window will also be closed. // fisrt, and when the web page is closed the window will also be closed.
shell_->CloseWebContents(); shell_->RequestToClosePage();
return NO; return NO;
} }
@ -303,8 +303,9 @@ SkRegion* DraggableRegionsToSkRegion(
} // namespace } // namespace
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, NativeWindowMac::NativeWindowMac(
const mate::Dictionary& options) brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options), : NativeWindow(web_contents, options),
is_kiosk_(false), is_kiosk_(false),
attention_request_id_(0) { attention_request_id_(0) {
@ -385,9 +386,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
} }
NativeWindowMac::~NativeWindowMac() { NativeWindowMac::~NativeWindowMac() {
// Force InspectableWebContents to be destroyed before we destroy window, Observe(nullptr);
// because it may still be observing the window at this time.
DestroyWebContents();
} }
void NativeWindowMac::Close() { void NativeWindowMac::Close() {
@ -678,10 +677,9 @@ void NativeWindowMac::SetOverlayIcon(const gfx::Image& overlay,
} }
void NativeWindowMac::ShowDefinitionForSelection() { void NativeWindowMac::ShowDefinitionForSelection() {
content::WebContents* web_contents = GetWebContents(); if (!web_contents())
if (!web_contents)
return; return;
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView(); auto rwhv = web_contents()->GetRenderWidgetHostView();
if (!rwhv) if (!rwhv)
return; return;
rwhv->ShowDefinitionForSelection(); rwhv->ShowDefinitionForSelection();
@ -705,10 +703,9 @@ bool NativeWindowMac::IsVisibleOnAllWorkspaces() {
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const { bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
if (!draggable_region_) if (!draggable_region_)
return false; return false;
content::WebContents* web_contents = GetWebContents(); if (!web_contents())
if (!web_contents)
return false; return false;
NSView* webView = web_contents->GetNativeView(); NSView* webView = web_contents()->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]); NSInteger webViewHeight = NSHeight([webView bounds]);
// |draggable_region_| is stored in local platform-indepdent coordiate system // |draggable_region_| is stored in local platform-indepdent coordiate system
// while |point| is in local Cocoa coordinate system. Do the conversion // while |point| is in local Cocoa coordinate system. Do the conversion
@ -815,16 +812,15 @@ void NativeWindowMac::UninstallView() {
} }
void NativeWindowMac::ClipWebView() { void NativeWindowMac::ClipWebView() {
content::WebContents* web_contents = GetWebContents(); if (!web_contents())
if (!web_contents)
return; return;
NSView* webView = web_contents->GetNativeView(); NSView* webView = web_contents()->GetNativeView();
webView.layer.masksToBounds = YES; webView.layer.masksToBounds = YES;
webView.layer.cornerRadius = kAtomWindowCornerRadius; webView.layer.cornerRadius = kAtomWindowCornerRadius;
} }
void NativeWindowMac::InstallDraggableRegionView() { void NativeWindowMac::InstallDraggableRegionView() {
NSView* webView = GetWebContents()->GetNativeView(); NSView* webView = web_contents()->GetNativeView();
base::scoped_nsobject<NSView> controlRegion( base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithShellWindow:this]); [[ControlRegionView alloc] initWithShellWindow:this]);
[controlRegion setFrame:NSMakeRect(0, 0, [controlRegion setFrame:NSMakeRect(0, 0,
@ -834,9 +830,10 @@ void NativeWindowMac::InstallDraggableRegionView() {
} }
// static // static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents, NativeWindow* NativeWindow::Create(
const mate::Dictionary& options) { brightray::InspectableWebContents* inspectable_web_contents,
return new NativeWindowMac(web_contents, options); const mate::Dictionary& options) {
return new NativeWindowMac(inspectable_web_contents, options);
} }
} // namespace atom } // namespace atom

View file

@ -16,7 +16,8 @@
#include "atom/common/draggable_region.h" #include "atom/common/draggable_region.h"
#include "atom/common/options_switches.h" #include "atom/common/options_switches.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "browser/inspectable_web_contents_view.h" #include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
@ -132,7 +133,7 @@ class NativeWindowClientView : public views::ClientView {
virtual ~NativeWindowClientView() {} virtual ~NativeWindowClientView() {}
bool CanClose() override { bool CanClose() override {
static_cast<NativeWindowViews*>(contents_view())->CloseWebContents(); static_cast<NativeWindowViews*>(contents_view())->RequestToClosePage();
return false; return false;
} }
@ -142,8 +143,9 @@ class NativeWindowClientView : public views::ClientView {
} // namespace } // namespace
NativeWindowViews::NativeWindowViews(content::WebContents* web_contents, NativeWindowViews::NativeWindowViews(
const mate::Dictionary& options) brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options), : NativeWindow(web_contents, options),
window_(new views::Widget), window_(new views::Widget),
web_view_(inspectable_web_contents()->GetView()->GetView()), web_view_(inspectable_web_contents()->GetView()->GetView()),
@ -726,9 +728,9 @@ void NativeWindowViews::OnWidgetActivationChanged(
else else
NotifyWindowBlur(); NotifyWindowBlur();
if (active && GetWebContents() && if (active && inspectable_web_contents() &&
!inspectable_web_contents()->IsDevToolsViewShowing()) !inspectable_web_contents()->IsDevToolsViewShowing())
GetWebContents()->Focus(); web_contents()->Focus();
// Hide menu bar when window is blured. // Hide menu bar when window is blured.
if (!active && menu_bar_autohide_ && menu_bar_visible_) if (!active && menu_bar_autohide_ && menu_bar_visible_)
@ -870,13 +872,6 @@ void NativeWindowViews::GetDevToolsWindowWMClass(
} }
#endif #endif
void NativeWindowViews::ActivateContents(content::WebContents* contents) {
NativeWindow::ActivateContents(contents);
// Hide menu bar when web view is clicked.
if (menu_bar_autohide_ && menu_bar_visible_)
SetMenuBarVisibility(false);
}
void NativeWindowViews::HandleKeyboardEvent( void NativeWindowViews::HandleKeyboardEvent(
content::WebContents*, content::WebContents*,
const content::NativeWebKeyboardEvent& event) { const content::NativeWebKeyboardEvent& event) {
@ -973,9 +968,10 @@ ui::WindowShowState NativeWindowViews::GetRestoredState() {
} }
// static // static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents, NativeWindow* NativeWindow::Create(
const mate::Dictionary& options) { brightray::InspectableWebContents* inspectable_web_contents,
return new NativeWindowViews(web_contents, options); const mate::Dictionary& options) {
return new NativeWindowViews(inspectable_web_contents, options);
} }
} // namespace atom } // namespace atom

View file

@ -28,9 +28,9 @@ class NativeWindowViews : public NativeWindow,
public views::WidgetDelegateView, public views::WidgetDelegateView,
public views::WidgetObserver { public views::WidgetObserver {
public: public:
explicit NativeWindowViews(content::WebContents* web_contents, NativeWindowViews(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options); const mate::Dictionary& options);
virtual ~NativeWindowViews(); ~NativeWindowViews() override;
// NativeWindow: // NativeWindow:
void Close() override; void Close() override;
@ -120,15 +120,14 @@ class NativeWindowViews : public NativeWindow,
bool ExecuteWindowsCommand(int command_id) override; bool ExecuteWindowsCommand(int command_id) override;
#endif #endif
// brightray::InspectableWebContentsDelegate: // brightray::InspectableWebContentsViewDelegate:
gfx::ImageSkia GetDevToolsWindowIcon() override; gfx::ImageSkia GetDevToolsWindowIcon() override;
#if defined(USE_X11) #if defined(USE_X11)
void GetDevToolsWindowWMClass( void GetDevToolsWindowWMClass(
std::string* name, std::string* class_name) override; std::string* name, std::string* class_name) override;
#endif #endif
// content::WebContentsDelegate: // NativeWindow:
void ActivateContents(content::WebContents* contents) override;
void HandleKeyboardEvent( void HandleKeyboardEvent(
content::WebContents*, content::WebContents*,
const content::NativeWebKeyboardEvent& event) override; const content::NativeWebKeyboardEvent& event) override;

View file

@ -0,0 +1,175 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/web_view_guest_delegate.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
namespace atom {
namespace {
const int kDefaultWidth = 300;
const int kDefaultHeight = 300;
} // namespace
WebViewGuestDelegate::WebViewGuestDelegate()
: guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false),
is_full_page_plugin_(false),
api_web_contents_(nullptr) {
}
WebViewGuestDelegate::~WebViewGuestDelegate() {
}
void WebViewGuestDelegate::Initialize(api::WebContents* api_web_contents) {
api_web_contents_ = api_web_contents;
Observe(api_web_contents->GetWebContents());
}
void WebViewGuestDelegate::Destroy() {
// Give the content module an opportunity to perform some cleanup.
guest_host_->WillDestroy();
guest_host_ = nullptr;
}
void WebViewGuestDelegate::SetSize(const SetSizeParams& params) {
bool enable_auto_size =
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
if (params.normal_size)
normal_size_ = *params.normal_size;
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
auto rvh = web_contents()->GetRenderViewHost();
if (enable_auto_size) {
// Autosize is being enabled.
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
normal_size_.SetSize(0, 0);
} else {
// Autosize is being disabled.
// Use default width/height if missing from partially defined normal size.
if (normal_size_.width() && !normal_size_.height())
normal_size_.set_height(GetDefaultSize().height());
if (!normal_size_.width() && normal_size_.height())
normal_size_.set_width(GetDefaultSize().width());
gfx::Size new_size;
if (!normal_size_.IsEmpty()) {
new_size = normal_size_;
} else if (!guest_size_.IsEmpty()) {
new_size = guest_size_;
} else {
new_size = GetDefaultSize();
}
if (auto_size_enabled_) {
// Autosize was previously enabled.
rvh->DisableAutoResize(new_size);
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
} else {
// Autosize was already disabled.
guest_host_->SizeContents(new_size);
}
guest_size_ = new_size;
}
auto_size_enabled_ = enable_auto_size;
}
void WebViewGuestDelegate::SetAllowTransparency(bool allow) {
if (guest_opaque_ != allow)
return;
auto render_view_host = web_contents()->GetRenderViewHost();
guest_opaque_ = !allow;
if (!render_view_host->GetView())
return;
if (guest_opaque_) {
render_view_host->GetView()->SetBackgroundColorToDefault();
} else {
render_view_host->GetView()->SetBackgroundColor(SK_ColorTRANSPARENT);
}
}
void WebViewGuestDelegate::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (embedder_web_contents_)
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(source, event);
}
void WebViewGuestDelegate::RenderViewReady() {
// We don't want to accidentally set the opacity of an interstitial page.
// WebContents::GetRenderWidgetHostView will return the RWHV of an
// interstitial page if one is showing at this time. We only want opacity
// to apply to web pages.
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
if (guest_opaque_)
render_view_host_view->SetBackgroundColorToDefault();
else
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
}
void WebViewGuestDelegate::DidAttach(int guest_proxy_routing_id) {
api_web_contents_->Emit("did-attach");
}
content::WebContents* WebViewGuestDelegate::GetOwnerWebContents() const {
return embedder_web_contents_;
}
void WebViewGuestDelegate::GuestSizeChanged(const gfx::Size& new_size) {
if (!auto_size_enabled_)
return;
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
guest_size_ = new_size;
}
void WebViewGuestDelegate::SetGuestHost(content::GuestHost* guest_host) {
guest_host_ = guest_host;
}
void WebViewGuestDelegate::WillAttach(
content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) {
embedder_web_contents_ = embedder_web_contents;
is_full_page_plugin_ = is_full_page_plugin;
}
void WebViewGuestDelegate::GuestSizeChangedDueToAutoSize(
const gfx::Size& old_size, const gfx::Size& new_size) {
api_web_contents_->Emit("size-changed",
old_size.width(), old_size.height(),
new_size.width(), new_size.height());
}
gfx::Size WebViewGuestDelegate::GetDefaultSize() const {
if (is_full_page_plugin_) {
// Full page plugins default to the size of the owner's viewport.
return embedder_web_contents_->GetRenderWidgetHostView()
->GetVisibleViewportSize();
} else {
return gfx::Size(kDefaultWidth, kDefaultHeight);
}
}
} // namespace atom

View file

@ -0,0 +1,122 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_WEB_VIEW_GUEST_DELEGATE_H_
#define ATOM_BROWSER_WEB_VIEW_GUEST_DELEGATE_H_
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
struct NativeWebKeyboardEvent;
}
namespace atom {
namespace api {
class WebContents;
}
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams() {}
~SetSizeParams() {}
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
public content::WebContentsObserver {
public:
WebViewGuestDelegate();
~WebViewGuestDelegate() override;
void Initialize(api::WebContents* api_web_contents);
// Called when the WebContents is going to be destroyed.
void Destroy();
// Used to toggle autosize mode for this GuestView, and set both the automatic
// and normal sizes.
void SetSize(const SetSizeParams& params);
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow);
// Transfer the keyboard event to embedder.
void HandleKeyboardEvent(content::WebContents* source,
const content::NativeWebKeyboardEvent& event);
protected:
// content::WebContentsObserver:
void RenderViewReady() override;
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) final;
private:
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
// Stores whether the contents of the guest can be transparent.
bool guest_opaque_;
// The WebContents that attaches this guest view.
content::WebContents* embedder_web_contents_;
// The size of the container element.
gfx::Size element_size_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// A pointer to the guest_host.
content::GuestHost* guest_host_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
api::WebContents* api_web_contents_;
DISALLOW_COPY_AND_ASSIGN(WebViewGuestDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_WEB_VIEW_GUEST_DELEGATE_H_

View file

@ -207,6 +207,8 @@
'atom/browser/ui/x/window_state_watcher.h', 'atom/browser/ui/x/window_state_watcher.h',
'atom/browser/ui/x/x_window_utils.cc', 'atom/browser/ui/x/x_window_utils.cc',
'atom/browser/ui/x/x_window_utils.h', 'atom/browser/ui/x/x_window_utils.h',
'atom/browser/web_view_guest_delegate.cc',
'atom/browser/web_view_guest_delegate.h',
'atom/browser/web_view_manager.cc', 'atom/browser/web_view_manager.cc',
'atom/browser/web_view_manager.h', 'atom/browser/web_view_manager.h',
'atom/browser/web_dialog_helper.cc', 'atom/browser/web_dialog_helper.cc',

2
vendor/brightray vendored

@ -1 +1 @@
Subproject commit 20871355cb590e009d7ee394a7d9da0e4666ea0b Subproject commit b05e019d2f66023fad1ae2f16cc765e3d62ffd5e