Decouple WebContentsDelegate from NativeWindow
authorCheng Zhao <zcbenz@gmail.com>
Thu, 25 Jun 2015 03:07:23 +0000 (11:07 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Thu, 25 Jun 2015 03:07:23 +0000 (11:07 +0800)
atom/browser/api/atom_api_web_contents.cc
atom/browser/api/atom_api_web_contents.h
atom/browser/api/atom_api_window.cc
atom/browser/api/atom_api_window.h
atom/browser/api/lib/browser-window.coffee
atom/browser/native_window.cc
atom/browser/native_window.h
atom/browser/native_window_mac.h
atom/browser/native_window_mac.mm
atom/browser/native_window_views.h

index a7877fa..dd05988 100644 (file)
@@ -142,12 +142,6 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
 
 }  // namespace
 
-WebContents::WebContents(brightray::InspectableWebContents* web_contents)
-    : WebContents(web_contents->GetWebContents()) {
-  type_ = BROWSER_WINDOW;
-  inspectable_web_contents_ = web_contents;
-}
-
 WebContents::WebContents(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       guest_opaque_(true),
@@ -210,8 +204,12 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
                                       const base::string16& message,
                                       int32 line_no,
                                       const base::string16& source_id) {
-  Emit("console-message", level, message, line_no, source_id);
-  return true;
+  if (type_ == BROWSER_WINDOW) {
+    return false;
+  } else {
+    Emit("console-message", level, message, line_no, source_id);
+    return true;
+  }
 }
 
 bool WebContents::ShouldCreateWebContents(
@@ -223,19 +221,21 @@ bool WebContents::ShouldCreateWebContents(
     const GURL& target_url,
     const std::string& partition_id,
     content::SessionStorageNamespace* session_storage_namespace) {
-  Emit("new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
+  if (type_ == BROWSER_WINDOW)
+    Emit("-new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
+  else
+    Emit("new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
   return false;
 }
 
-void WebContents::CloseContents(content::WebContents* source) {
-  Emit("close");
-}
-
 content::WebContents* WebContents::OpenURLFromTab(
     content::WebContents* source,
     const content::OpenURLParams& params) {
   if (params.disposition != CURRENT_TAB) {
-    Emit("new-window", params.url, "", params.disposition);
+    if (type_ == BROWSER_WINDOW)
+      Emit("-new-window", params.url, "", params.disposition);
+    else
+      Emit("new-window", params.url, "", params.disposition);
     return nullptr;
   }
 
@@ -246,6 +246,31 @@ content::WebContents* WebContents::OpenURLFromTab(
   return CommonWebContentsDelegate::OpenURLFromTab(source, params);
 }
 
+void WebContents::BeforeUnloadFired(content::WebContents* tab,
+                                    bool proceed,
+                                    bool* proceed_to_fire_unload) {
+  if (type_ == BROWSER_WINDOW)
+    *proceed_to_fire_unload = proceed;
+  else
+    *proceed_to_fire_unload = true;
+}
+
+void WebContents::MoveContents(content::WebContents* source,
+                               const gfx::Rect& pos) {
+  Emit("move", pos);
+}
+
+void WebContents::CloseContents(content::WebContents* source) {
+  Emit("closed");
+  if (type_ == BROWSER_WINDOW)
+    owner_window()->CloseContents(source);
+}
+
+void WebContents::ActivateContents(content::WebContents* source) {
+  if (type_ == BROWSER_WINDOW)
+    owner_window()->CloseContents(source);
+}
+
 bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
   return type_ == BROWSER_WINDOW;
 }
@@ -253,12 +278,12 @@ bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
 void WebContents::HandleKeyboardEvent(
     content::WebContents* source,
     const content::NativeWebKeyboardEvent& event) {
-  if (!attached())
-    return;
-
-  // Send the unhandled keyboard events back to the embedder to reprocess them.
-  embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
-      web_contents(), event);
+  if (type_ == BROWSER_WINDOW) {
+    owner_window()->HandleKeyboardEvent(source, event);
+  } else if (type_ == WEB_VIEW && !attached()) {
+    // Send the unhandled keyboard events back to the embedder.
+    embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(source, event);
+  }
 }
 
 void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
@@ -272,6 +297,23 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
   Emit("leave-html-full-screen");
 }
 
+void WebContents::RendererUnresponsive(content::WebContents* source) {
+  Emit("unresponsive");
+  if (type_ == BROWSER_WINDOW)
+    owner_window()->RendererUnresponsive(source);
+}
+
+void WebContents::RendererResponsive(content::WebContents* source) {
+  Emit("responsive");
+  if (type_ == BROWSER_WINDOW)
+    owner_window()->RendererResponsive(source);
+}
+
+void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
+  // Do nothing, we override this method just to avoid compilation error since
+  // there are two virtual functions named BeforeUnloadFired.
+}
+
 void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
   int process_id = render_view_host->GetProcess()->GetID();
   Emit("render-view-deleted", process_id);
@@ -900,21 +942,6 @@ gfx::Size WebContents::GetDefaultSize() const {
 
 // static
 mate::Handle<WebContents> WebContents::CreateFrom(
-    v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) {
-  // We have an existing WebContents object in JS.
-  auto existing = TrackableObject::FromWrappedClass(
-      isolate, web_contents->GetWebContents());
-  if (existing)
-    return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
-
-  // Otherwise create a new WebContents wrapper object.
-  auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
-  g_wrap_web_contents.Run(handle.ToV8());
-  return handle;
-}
-
-// static
-mate::Handle<WebContents> WebContents::CreateFrom(
     v8::Isolate* isolate, content::WebContents* web_contents) {
   // We have an existing WebContents object in JS.
   auto existing = TrackableObject::FromWrappedClass(isolate, web_contents);
index be874d9..55f0877 100644 (file)
@@ -58,8 +58,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
 
   // Create from an existing WebContents.
   static mate::Handle<WebContents> CreateFrom(
-      v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
-  static mate::Handle<WebContents> CreateFrom(
       v8::Isolate* isolate, content::WebContents* web_contents);
 
   // Create a new WebContents.
@@ -136,7 +134,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
   }
 
  protected:
-  explicit WebContents(brightray::InspectableWebContents* web_contents);
   explicit WebContents(content::WebContents* web_contents);
   explicit WebContents(const mate::Dictionary& options);
   ~WebContents();
@@ -160,10 +157,16 @@ class WebContents : public mate::TrackableObject<WebContents>,
       const GURL& target_url,
       const std::string& partition_id,
       content::SessionStorageNamespace* session_storage_namespace) override;
-  void CloseContents(content::WebContents* source) override;
   content::WebContents* OpenURLFromTab(
       content::WebContents* source,
       const content::OpenURLParams& params) override;
+  void BeforeUnloadFired(content::WebContents* tab,
+                         bool proceed,
+                         bool* proceed_to_fire_unload) override;
+  void MoveContents(content::WebContents* source,
+                    const gfx::Rect& pos) override;
+  void CloseContents(content::WebContents* source) override;
+  void ActivateContents(content::WebContents* contents) override;
   bool IsPopupOrPanel(const content::WebContents* source) const override;
   void HandleKeyboardEvent(
       content::WebContents* source,
@@ -171,8 +174,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
   void EnterFullscreenModeForTab(content::WebContents* source,
                                  const GURL& origin) override;
   void ExitFullscreenModeForTab(content::WebContents* source) override;
+  void RendererUnresponsive(content::WebContents* source) override;
+  void RendererResponsive(content::WebContents* source) override;
 
   // content::WebContentsObserver:
+  void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
   void RenderViewDeleted(content::RenderViewHost*) override;
   void RenderProcessGone(base::TerminationStatus status) override;
   void DocumentLoadedInFrame(
index 9869e36..2dae7f8 100644 (file)
@@ -43,6 +43,7 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
   mate::Dictionary web_contents_options(isolate, v8::Object::New(isolate));
   auto web_contents = WebContents::Create(isolate, web_contents_options);
   web_contents_.Reset(isolate, web_contents.ToV8());
+  api_web_contents_ = web_contents.get();
 
   // Creates BrowserWindow.
   window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
@@ -62,17 +63,6 @@ void Window::OnPageTitleUpdated(bool* prevent_default,
   *prevent_default = Emit("page-title-updated", title);
 }
 
-void Window::WillCreatePopupWindow(const base::string16& frame_name,
-                                   const GURL& target_url,
-                                   const std::string& partition_id,
-                                   WindowOpenDisposition disposition) {
-  Emit("-new-window", target_url, frame_name);
-}
-
-void Window::WillNavigate(bool* prevent_default, const GURL& url) {
-  *prevent_default = Emit("-will-navigate", url);
-}
-
 void Window::WillCloseWindow(bool* prevent_default) {
   *prevent_default = Emit("close");
 }
@@ -80,6 +70,12 @@ void Window::WillCloseWindow(bool* prevent_default) {
 void Window::OnWindowClosed() {
   Emit("closed");
 
+  if (api_web_contents_) {
+    api_web_contents_->DestroyWebContents();
+    api_web_contents_ = nullptr;
+    web_contents_.Reset();
+  }
+
   RemoveFromWeakMap();
   window_->RemoveObserver(this);
 }
@@ -153,8 +149,8 @@ void Window::OnDevToolsOpened() {
 
   v8::Locker locker(isolate());
   v8::HandleScope handle_scope(isolate());
-  auto handle = WebContents::CreateFrom(isolate(),
-                                        window_->GetDevToolsWebContents());
+  auto handle = WebContents::CreateFrom(
+      isolate(), api_web_contents_->GetDevToolsWebContents());
   devtools_web_contents_.Reset(isolate(), handle.ToV8());
 }
 
@@ -178,8 +174,7 @@ mate::Wrappable* Window::New(v8::Isolate* isolate,
 }
 
 void Window::Destroy() {
-  window_->DestroyWebContents();
-  window_->CloseImmediately();
+  window_->CloseContents(nullptr);
 }
 
 void Window::Close() {
index f6c99eb..41383ea 100644 (file)
@@ -51,11 +51,6 @@ class Window : public mate::TrackableObject<Window>,
   // NativeWindowObserver:
   void OnPageTitleUpdated(bool* prevent_default,
                           const std::string& title) override;
-  void WillCreatePopupWindow(const base::string16& frame_name,
-                             const GURL& target_url,
-                             const std::string& partition_id,
-                             WindowOpenDisposition disposition) override;
-  void WillNavigate(bool* prevent_default, const GURL& url) override;
   void WillCloseWindow(bool* prevent_default) override;
   void OnWindowClosed() override;
   void OnWindowBlur() override;
@@ -151,6 +146,8 @@ class Window : public mate::TrackableObject<Window>,
   v8::Global<v8::Value> devtools_web_contents_;
   v8::Global<v8::Value> menu_;
 
+  api::WebContents* api_web_contents_;
+
   scoped_ptr<NativeWindow> window_;
 
   DISALLOW_COPY_AND_ASSIGN(Window);
index 66e0670..24ae7b8 100644 (file)
@@ -12,14 +12,13 @@ BrowserWindow::_init = ->
     @setMenu menu if menu?
 
   # Make new windows requested by links behave like "window.open"
-  @on '-new-window', (event, url, frameName) =>
-    event.sender = @webContents
+  @webContents.on '-new-window', (event, url, frameName) ->
     options = show: true, width: 800, height: 600
     ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
 
-  # Redirect "will-navigate" to webContents.
-  @on '-will-navigate', (event, url) =>
-    @webContents.emit 'will-navigate', event, url
+  # window.move(...)
+  @webContents.on 'move', (event, size) =>
+    @setSize size
 
   # Redirect focus/blur event to app instance too.
   @on 'blur', (event) =>
index fc32ee7..8748388 100644 (file)
@@ -94,6 +94,7 @@ NativeWindow::NativeWindow(
       node_integration_(true),
       has_dialog_attached_(false),
       zoom_factor_(1.0),
+      inspectable_web_contents_(inspectable_web_contents),
       weak_factory_(this) {
   options.Get(switches::kFrame, &has_frame_);
   options.Get(switches::kTransparent, &transparent_);
@@ -341,6 +342,13 @@ void NativeWindow::CloseWebContents() {
     web_contents->Close();
 }
 
+content::WebContents* NativeWindow::GetWebContents() const {
+  if (inspectable_web_contents_)
+    return inspectable_web_contents_->GetWebContents();
+  else
+    return nullptr;
+}
+
 void NativeWindow::AppendExtraCommandLineSwitches(
     base::CommandLine* command_line) {
   // Append --node-integration to renderer process.
@@ -475,52 +483,6 @@ void NativeWindow::NotifyWindowLeaveHtmlFullScreen() {
                     OnWindowLeaveHtmlFullScreen());
 }
 
-bool NativeWindow::ShouldCreateWebContents(
-    content::WebContents* web_contents,
-    int route_id,
-    int main_frame_route_id,
-    WindowContainerType window_container_type,
-    const base::string16& frame_name,
-    const GURL& target_url,
-    const std::string& partition_id,
-    content::SessionStorageNamespace* session_storage_namespace) {
-  FOR_EACH_OBSERVER(NativeWindowObserver,
-                    observers_,
-                    WillCreatePopupWindow(frame_name,
-                                          target_url,
-                                          partition_id,
-                                          NEW_FOREGROUND_TAB));
-  return false;
-}
-
-// In atom-shell all reloads and navigations started by renderer process would
-// be redirected to this method, so we can have precise control of how we
-// would open the url (in our case, is to restart the renderer process). See
-// AtomRendererClient::ShouldFork for how this is done.
-content::WebContents* NativeWindow::OpenURLFromTab(
-    content::WebContents* source,
-    const content::OpenURLParams& params) {
-  if (params.disposition != CURRENT_TAB) {
-    FOR_EACH_OBSERVER(NativeWindowObserver,
-                      observers_,
-                      WillCreatePopupWindow(base::string16(),
-                                            params.url,
-                                            "",
-                                            params.disposition));
-    return nullptr;
-  }
-
-  // Give user a chance to prevent navigation.
-  bool prevent_default = false;
-  FOR_EACH_OBSERVER(NativeWindowObserver,
-                    observers_,
-                    WillNavigate(&prevent_default, params.url));
-  if (prevent_default)
-    return nullptr;
-
-  return CommonWebContentsDelegate::OpenURLFromTab(source, params);
-}
-
 void NativeWindow::RenderViewCreated(
     content::RenderViewHost* render_view_host) {
   if (!transparent_)
@@ -533,20 +495,8 @@ void NativeWindow::RenderViewCreated(
     impl->SetBackgroundOpaque(false);
 }
 
-void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
-                                     bool proceed,
-                                     bool* proceed_to_fire_unload) {
-  *proceed_to_fire_unload = proceed;
-}
-
-void NativeWindow::MoveContents(content::WebContents* source,
-                                const gfx::Rect& pos) {
-  SetBounds(pos);
-}
-
 void NativeWindow::CloseContents(content::WebContents* source) {
-  // Destroy the WebContents before we close the window.
-  DestroyWebContents();
+  inspectable_web_contents_ = nullptr;
 
   // When the web contents is gone, close the window immediately, but the
   // memory will not be freed until you call delete.
@@ -575,11 +525,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
   FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
 }
 
-void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
-  // Do nothing, we override this method just to avoid compilation error since
-  // there are two virtual functions named BeforeUnloadFired.
-}
-
 void NativeWindow::BeforeUnloadDialogCancelled() {
   WindowList::WindowCloseCancelled(this);
 
@@ -609,18 +554,6 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
   return handled;
 }
 
-void NativeWindow::DevToolsFocused() {
-  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
-}
-
-void NativeWindow::DevToolsOpened() {
-  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
-}
-
-void NativeWindow::DevToolsClosed() {
-  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
-}
-
 void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
   if (!window_unresposive_closure_.IsCancelled())
     return;
index 0f06145..8fe5143 100644 (file)
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "atom/browser/common_web_contents_delegate.h"
 #include "atom/browser/native_window_observer.h"
 #include "atom/browser/ui/accelerator_util.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "content/public/browser/readback_types.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "native_mate/persistent_dictionary.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace base {
 class CommandLine;
 }
 
+namespace brightray {
+class InspectableWebContents;
+}
+
 namespace content {
-class BrowserContext;
-class WebContents;
+struct NativeWebKeyboardEvent;
 struct WebPreferences;
 }
 
@@ -49,8 +53,7 @@ namespace atom {
 
 struct DraggableRegion;
 
-class NativeWindow : public CommonWebContentsDelegate,
-                     public content::WebContentsObserver {
+class NativeWindow : public content::WebContentsObserver {
  public:
   typedef base::Callback<void(const SkBitmap& bitmap)> CapturePageCallback;
 
@@ -167,6 +170,17 @@ class NativeWindow : public CommonWebContentsDelegate,
     return weak_factory_.GetWeakPtr();
   }
 
+  content::WebContents* GetWebContents() const;
+
+  // Methods called by the WebContents.
+  virtual void CloseContents(content::WebContents* source);
+  virtual void RendererUnresponsive(content::WebContents* source);
+  virtual void RendererResponsive(content::WebContents* source);
+  virtual void ActivateContents(content::WebContents* contents) {}
+  virtual void HandleKeyboardEvent(
+      content::WebContents*,
+      const content::NativeWebKeyboardEvent& event) {}
+
   // Called when renderer process is going to be started.
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
   void OverrideWebkitPrefs(content::WebPreferences* prefs);
@@ -214,40 +228,12 @@ class NativeWindow : public CommonWebContentsDelegate,
   virtual void UpdateDraggableRegions(
       const std::vector<DraggableRegion>& regions) = 0;
 
-  // Implementations of content::WebContentsDelegate.
-  bool ShouldCreateWebContents(
-      content::WebContents* web_contents,
-      int route_id,
-      int main_frame_route_id,
-      WindowContainerType window_container_type,
-      const base::string16& frame_name,
-      const GURL& target_url,
-      const std::string& partition_id,
-      content::SessionStorageNamespace* session_storage_namespace) override;
-  content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) override;
-  void BeforeUnloadFired(content::WebContents* tab,
-                         bool proceed,
-                         bool* proceed_to_fire_unload) override;
-  void MoveContents(content::WebContents* source,
-                    const gfx::Rect& pos) override;
-  void CloseContents(content::WebContents* source) override;
-  void RendererUnresponsive(content::WebContents* source) override;
-  void RendererResponsive(content::WebContents* source) override;
-
   // Implementations of content::WebContentsObserver.
   void RenderViewCreated(content::RenderViewHost* render_view_host) override;
-  void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
   void BeforeUnloadDialogCancelled() override;
   void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  // Implementations of brightray::InspectableWebContentsDelegate.
-  void DevToolsFocused() override;
-  void DevToolsOpened() override;
-  void DevToolsClosed() override;
-
   // Whether window has standard frame.
   bool has_frame_;
 
index 7f9272b..67f4389 100644 (file)
@@ -27,7 +27,7 @@ class NativeWindowMac : public NativeWindow {
                   const mate::Dictionary& options);
   ~NativeWindowMac() override;
 
-  // NativeWindow implementation.
+  // NativeWindow:
   void Close() override;
   void CloseImmediately() override;
   void Focus(bool focus) override;
@@ -91,7 +91,7 @@ class NativeWindowMac : public NativeWindow {
   void UpdateDraggableRegions(
       const std::vector<DraggableRegion>& regions) override;
 
-  // Implementations of content::WebContentsDelegate.
+  // NativeWindow:
   void HandleKeyboardEvent(
       content::WebContents*,
       const content::NativeWebKeyboardEvent&) override;
index 093b183..5c17ee3 100644 (file)
@@ -386,9 +386,7 @@ NativeWindowMac::NativeWindowMac(
 }
 
 NativeWindowMac::~NativeWindowMac() {
-  // Force InspectableWebContents to be destroyed before we destroy window,
-  // because it may still be observing the window at this time.
-  DestroyWebContents();
+  Observe(nullptr);
 }
 
 void NativeWindowMac::Close() {
index 6211225..c446d53 100644 (file)
@@ -127,7 +127,7 @@ class NativeWindowViews : public NativeWindow,
       std::string* name, std::string* class_name) override;
 #endif
 
-  // content::WebContentsDelegate:
+  // NativeWindow:
   void ActivateContents(content::WebContents* contents) override;
   void HandleKeyboardEvent(
       content::WebContents*,