Browse Source

Refactor NativeWindow (Part 6): Move NativeWindow bindings to api::TopLevelWindow (#12596)

* Add atom::api::TopLevelWindow

* Make BrowserWindow inherit TopLevelWindow

* Fix reading from wrong weak map

* Read options after setting content view

* OnWindowClosed is not guarenteed to run now

* Fix the offscreen hack in BrowserWindow

* Fix building on Linux

* Fix tests on Linux

* Fix building on Windows
Cheng Zhao 7 years ago
parent
commit
858828d343

File diff suppressed because it is too large
+ 36 - 877
atom/browser/api/atom_api_browser_window.cc


+ 23 - 211
atom/browser/api/atom_api_browser_window.h

@@ -5,43 +5,21 @@
 #ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
 #define ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
 
-#include <map>
-#include <memory>
 #include <string>
 #include <vector>
 
+#include "atom/browser/api/atom_api_top_level_window.h"
 #include "atom/browser/api/atom_api_web_contents.h"
-#include "atom/browser/native_window.h"
-#include "atom/browser/native_window_observer.h"
-#include "atom/common/api/atom_api_native_image.h"
-#include "atom/common/key_weak_map.h"
 #include "base/cancelable_callback.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/render_widget_host.h"
-#include "native_mate/persistent_dictionary.h"
-
-class GURL;
-
-namespace gfx {
-class Rect;
-}
-
-namespace mate {
-class Arguments;
-class Dictionary;
-}
 
 namespace atom {
 
-class NativeWindow;
-
 namespace api {
 
-class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
+class BrowserWindow : public TopLevelWindow,
                       public content::RenderWidgetHost::InputEventObserver,
                       public content::WebContentsObserver,
-                      public ExtendedWebContentsObserver,
-                      public NativeWindowObserver {
+                      public ExtendedWebContentsObserver {
  public:
   static mate::WrappableBase* New(mate::Arguments* args);
 
@@ -52,9 +30,9 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
   static v8::Local<v8::Value> From(v8::Isolate* isolate,
                                    NativeWindow* native_window);
 
-  NativeWindow* window() const { return window_.get(); }
-
-  int32_t ID() const;
+  base::WeakPtr<BrowserWindow> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
 
  protected:
   BrowserWindow(v8::Isolate* isolate,
@@ -80,184 +58,28 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
   void OnRendererResponsive() override;
 
   // NativeWindowObserver:
-  void WillCloseWindow(bool* prevent_default) override;
   void RequestPreferredWidth(int* width) override;
   void OnCloseButtonClicked(bool* prevent_default) override;
+
+  // TopLevelWindow:
   void OnWindowClosed() override;
-  void OnWindowEndSession() override;
   void OnWindowBlur() override;
   void OnWindowFocus() override;
-  void OnWindowShow() override;
-  void OnWindowHide() override;
-  void OnWindowMaximize() override;
-  void OnWindowUnmaximize() override;
-  void OnWindowMinimize() override;
-  void OnWindowRestore() override;
   void OnWindowResize() override;
-  void OnWindowMove() override;
-  void OnWindowMoved() override;
-  void OnWindowScrollTouchBegin() override;
-  void OnWindowScrollTouchEnd() override;
-  void OnWindowSwipe(const std::string& direction) override;
-  void OnWindowSheetBegin() override;
-  void OnWindowSheetEnd() override;
-  void OnWindowEnterFullScreen() override;
-  void OnWindowLeaveFullScreen() override;
-  void OnWindowEnterHtmlFullScreen() override;
-  void OnWindowLeaveHtmlFullScreen() override;
-  void OnExecuteWindowsCommand(const std::string& command_name) override;
-  void OnTouchBarItemResult(const std::string& item_id,
-                            const base::DictionaryValue& details) override;
-  void OnNewWindowForTab() override;
-
-  #if defined(OS_WIN)
-  void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
-  #endif
-
-  base::WeakPtr<BrowserWindow> GetWeakPtr() {
-    return weak_factory_.GetWeakPtr();
-  }
+  void Focus() override;
+  void Blur() override;
+  void SetBackgroundColor(const std::string& color_name) override;
+  void SetBrowserView(v8::Local<v8::Value> value) override;
+  void SetVibrancy(mate::Arguments* args) override;
 
- private:
-  void Init(v8::Isolate* isolate,
-            v8::Local<v8::Object> wrapper,
-            const mate::Dictionary& options,
-            mate::Handle<class WebContents> web_contents);
-
-  // APIs for NativeWindow.
-  void Close();
-  void Focus();
-  void Blur();
-  bool IsFocused();
-  void Show();
-  void ShowInactive();
-  void Hide();
-  bool IsVisible();
-  bool IsEnabled();
-  void SetEnabled(bool enable);
-  void Maximize();
-  void Unmaximize();
-  bool IsMaximized();
-  void Minimize();
-  void Restore();
-  bool IsMinimized();
-  void SetFullScreen(bool fullscreen);
-  bool IsFullscreen();
-  void SetBounds(const gfx::Rect& bounds, mate::Arguments* args);
-  gfx::Rect GetBounds();
-  void SetSize(int width, int height, mate::Arguments* args);
-  std::vector<int> GetSize();
-  void SetContentSize(int width, int height, mate::Arguments* args);
-  std::vector<int> GetContentSize();
-  void SetContentBounds(const gfx::Rect& bounds, mate::Arguments* args);
-  gfx::Rect GetContentBounds();
-  void SetMinimumSize(int width, int height);
-  std::vector<int> GetMinimumSize();
-  void SetMaximumSize(int width, int height);
-  std::vector<int> GetMaximumSize();
-  void SetSheetOffset(double offsetY, mate::Arguments* args);
-  void SetResizable(bool resizable);
-  bool IsResizable();
-  void SetMovable(bool movable);
-  #if defined(OS_WIN) || defined(OS_MACOSX)
-  void MoveTop();
-  #endif
-  bool IsMovable();
-  void SetMinimizable(bool minimizable);
-  bool IsMinimizable();
-  void SetMaximizable(bool maximizable);
-  bool IsMaximizable();
-  void SetFullScreenable(bool fullscreenable);
-  bool IsFullScreenable();
-  void SetClosable(bool closable);
-  bool IsClosable();
-  void SetAlwaysOnTop(bool top, mate::Arguments* args);
-  bool IsAlwaysOnTop();
-  void Center();
-  void SetPosition(int x, int y, mate::Arguments* args);
-  std::vector<int> GetPosition();
-  void SetTitle(const std::string& title);
-  std::string GetTitle();
-  void FlashFrame(bool flash);
-  void SetSkipTaskbar(bool skip);
-  void SetSimpleFullScreen(bool simple_fullscreen);
-  bool IsSimpleFullScreen();
-  void SetKiosk(bool kiosk);
-  bool IsKiosk();
-  void SetBackgroundColor(const std::string& color_name);
-  void SetHasShadow(bool has_shadow);
-  bool HasShadow();
-  void SetOpacity(const double opacity);
-  double GetOpacity();
+  // BrowserWindow APIs.
   void FocusOnWebView();
   void BlurWebView();
   bool IsWebViewFocused();
-  void SetRepresentedFilename(const std::string& filename);
-  std::string GetRepresentedFilename();
-  void SetDocumentEdited(bool edited);
-  bool IsDocumentEdited();
-  void SetIgnoreMouseEvents(bool ignore, mate::Arguments* args);
-  void SetContentProtection(bool enable);
-  void SetFocusable(bool focusable);
-  void SetProgressBar(double progress, mate::Arguments* args);
-  void SetOverlayIcon(const gfx::Image& overlay,
-                      const std::string& description);
-  bool SetThumbarButtons(mate::Arguments* args);
-  void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
-  void SetAutoHideMenuBar(bool auto_hide);
-  bool IsMenuBarAutoHide();
-  void SetMenuBarVisibility(bool visible);
-  bool IsMenuBarVisible();
-  void SetAspectRatio(double aspect_ratio, mate::Arguments* args);
-  void PreviewFile(const std::string& path, mate::Arguments* args);
-  void CloseFilePreview();
-  void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
-  v8::Local<v8::Value> GetParentWindow() const;
-  std::vector<v8::Local<v8::Object>> GetChildWindows() const;
-  v8::Local<v8::Value> GetBrowserView() const;
-  void SetBrowserView(v8::Local<v8::Value> value);
-  void ResetBrowserView();
-  bool IsModal() const;
-  v8::Local<v8::Value> GetNativeWindowHandle();
-
-#if defined(OS_WIN)
-  typedef base::Callback<void(v8::Local<v8::Value>,
-                              v8::Local<v8::Value>)> MessageCallback;
-
-  bool HookWindowMessage(UINT message, const MessageCallback& callback);
-  bool IsWindowMessageHooked(UINT message);
-  void UnhookWindowMessage(UINT message);
-  void UnhookAllWindowMessages();
-  bool SetThumbnailClip(const gfx::Rect& region);
-  bool SetThumbnailToolTip(const std::string& tooltip);
-  void SetAppDetails(const mate::Dictionary& options);
-#endif
-
-#if defined(TOOLKIT_VIEWS)
-  void SetIcon(mate::Handle<NativeImage> icon);
-#endif
+  v8::Local<v8::Value> GetWebContents(v8::Isolate* isolate);
 
-  void SetVisibleOnAllWorkspaces(bool visible);
-  bool IsVisibleOnAllWorkspaces();
-
-  void SetAutoHideCursor(bool auto_hide);
-
-  void SelectPreviousTab();
-  void SelectNextTab();
-  void MergeAllWindows();
-  void MoveTabToNewWindow();
-  void ToggleTabBar();
-  void AddTabbedWindow(NativeWindow* window, mate::Arguments* args);
-
-  void SetVibrancy(mate::Arguments* args);
-  void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
-  void RefreshTouchBarItem(const std::string& item_id);
-  void SetEscapeTouchBarItem(const mate::PersistentDictionary& item);
-
-  v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
-
-  // Remove this window from parent window's |child_windows_|.
-  void RemoveFromParentChildWindows();
+ private:
+  // Helpers.
 
   // Called when the window needs to update its draggable region.
   void UpdateDraggableRegions(
@@ -274,29 +96,20 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
   // Dispatch unresponsive event to observers.
   void NotifyWindowUnresponsive();
 
-#if defined(OS_WIN)
-  typedef std::map<UINT, MessageCallback> MessageCallbackMap;
-  MessageCallbackMap messages_callback_map_;
-#endif
-
-#if defined(OS_MACOSX)
-  std::vector<DraggableRegion> draggable_regions_;
-#endif
+  // Cleanup our WebContents observers.
+  void Cleanup();
 
   // Closure that would be called when window is unresponsive when closing,
   // it should be cancelled when we can prove that the window is responsive.
   base::CancelableClosure window_unresponsive_closure_;
 
-  v8::Global<v8::Value> browser_view_;
-  v8::Global<v8::Value> web_contents_;
-  v8::Global<v8::Value> menu_;
-  v8::Global<v8::Value> parent_window_;
-  KeyWeakMap<int> child_windows_;
+#if defined(OS_MACOSX)
+  std::vector<DraggableRegion> draggable_regions_;
+#endif
 
+  v8::Global<v8::Value> web_contents_;
   api::WebContents* api_web_contents_;
 
-  std::unique_ptr<NativeWindow> window_;
-
   base::WeakPtrFactory<BrowserWindow> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
@@ -306,7 +119,6 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
 
 }  // namespace atom
 
-
 namespace mate {
 
 template<>

+ 2 - 1
atom/browser/api/atom_api_menu_mac.mm

@@ -35,7 +35,8 @@ void MenuMac::PopupAt(BrowserWindow* window,
     return;
 
   auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
-                          native_window->GetWeakPtr(), window->ID(), x, y,
+                          native_window->GetWeakPtr(),
+                          window->weak_map_id(), x, y,
                           positioning_item, callback);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
 }

+ 1 - 1
atom/browser/api/atom_api_menu_views.cc

@@ -43,7 +43,7 @@ void MenuViews::PopupAt(BrowserWindow* window,
   atom::UnresponsiveSuppressor suppressor;
 
   // Show the menu.
-  int32_t window_id = window->ID();
+  int32_t window_id = window->weak_map_id();
   auto close_callback = base::Bind(
       &MenuViews::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
   menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(

+ 1057 - 0
atom/browser/api/atom_api_top_level_window.cc

@@ -0,0 +1,1057 @@
+// Copyright (c) 2018 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/api/atom_api_top_level_window.h"
+
+#include <string>
+#include <vector>
+
+#include "atom/browser/api/atom_api_browser_view.h"
+#include "atom/browser/api/atom_api_menu.h"
+#include "atom/common/color_util.h"
+#include "atom/common/native_mate_converters/callback.h"
+#include "atom/common/native_mate_converters/file_path_converter.h"
+#include "atom/common/native_mate_converters/gfx_converter.h"
+#include "atom/common/native_mate_converters/image_converter.h"
+#include "atom/common/native_mate_converters/string16_converter.h"
+#include "atom/common/native_mate_converters/value_converter.h"
+#include "atom/common/options_switches.h"
+#include "native_mate/handle.h"
+#include "native_mate/persistent_dictionary.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "atom/browser/native_window_views.h"
+#endif
+
+#if defined(OS_WIN)
+#include "atom/browser/ui/win/taskbar_host.h"
+#include "ui/base/win/shell.h"
+#endif
+
+#include "atom/common/node_includes.h"
+
+#if defined(OS_WIN)
+namespace mate {
+
+template<>
+struct Converter<atom::TaskbarHost::ThumbarButton> {
+  static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+                     atom::TaskbarHost::ThumbarButton* out) {
+    mate::Dictionary dict;
+    if (!ConvertFromV8(isolate, val, &dict))
+      return false;
+    dict.Get("click", &(out->clicked_callback));
+    dict.Get("tooltip", &(out->tooltip));
+    dict.Get("flags", &out->flags);
+    return dict.Get("icon", &(out->icon));
+  }
+};
+
+}  // namespace mate
+#endif
+
+namespace atom {
+
+namespace api {
+
+namespace {
+
+// Converts binary data to Buffer.
+v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
+  auto buffer = node::Buffer::Copy(isolate, static_cast<char*>(val), size);
+  if (buffer.IsEmpty())
+    return v8::Null(isolate);
+  else
+    return buffer.ToLocalChecked();
+}
+
+}  // namespace
+
+TopLevelWindow::TopLevelWindow(v8::Isolate* isolate,
+                               v8::Local<v8::Object> wrapper,
+                               const mate::Dictionary& options)
+    : weak_factory_(this) {
+  // The parent window.
+  mate::Handle<TopLevelWindow> parent;
+  if (options.Get("parent", &parent) && !parent.IsEmpty())
+    parent_window_.Reset(isolate, parent.ToV8());
+
+#if defined(ENABLE_OSR)
+  // Offscreen windows are always created frameless.
+  mate::Dictionary web_preferences;
+  bool offscreen;
+  if (options.Get(options::kWebPreferences, &web_preferences) &&
+      web_preferences.Get("offscreen", &offscreen) &&
+      offscreen) {
+    const_cast<mate::Dictionary&>(options).Set(options::kFrame, false);
+  }
+#endif
+
+  // Creates NativeWindow.
+  window_.reset(NativeWindow::Create(
+      options,
+      parent.IsEmpty() ? nullptr : parent->window_.get()));
+  window_->AddObserver(this);
+
+#if defined(TOOLKIT_VIEWS)
+  // Sets the window icon.
+  mate::Handle<NativeImage> icon;
+  if (options.Get(options::kIcon, &icon) && !icon.IsEmpty())
+    SetIcon(icon);
+#endif
+
+  AttachAsUserData(window_.get());
+
+  // We can only append this window to parent window's child windows after this
+  // window's JS wrapper gets initialized.
+  if (!parent.IsEmpty())
+    parent->child_windows_.Set(isolate, weak_map_id(), wrapper);
+}
+
+TopLevelWindow::~TopLevelWindow() {
+  if (!window_->IsClosed())
+    window_->CloseImmediately();
+
+  // Destroy the native window in next tick because the native code might be
+  // iterating all windows.
+  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release());
+}
+
+void TopLevelWindow::WillCloseWindow(bool* prevent_default) {
+  *prevent_default = Emit("close");
+}
+
+void TopLevelWindow::OnWindowClosed() {
+  RemoveFromWeakMap();
+  window_->RemoveObserver(this);
+
+  // We can not call Destroy here because we need to call Emit first, but we
+  // also do not want any method to be used, so just mark as destroyed here.
+  MarkDestroyed();
+
+  Emit("closed");
+
+  RemoveFromParentChildWindows();
+  ResetBrowserView();
+
+  // Destroy the native class when window is closed.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
+}
+
+void TopLevelWindow::OnWindowEndSession() {
+  Emit("session-end");
+}
+
+void TopLevelWindow::OnWindowBlur() {
+  Emit("blur");
+}
+
+void TopLevelWindow::OnWindowFocus() {
+  Emit("focus");
+}
+
+void TopLevelWindow::OnWindowShow() {
+  Emit("show");
+}
+
+void TopLevelWindow::OnWindowHide() {
+  Emit("hide");
+}
+
+void TopLevelWindow::OnWindowMaximize() {
+  Emit("maximize");
+}
+
+void TopLevelWindow::OnWindowUnmaximize() {
+  Emit("unmaximize");
+}
+
+void TopLevelWindow::OnWindowMinimize() {
+  Emit("minimize");
+}
+
+void TopLevelWindow::OnWindowRestore() {
+  Emit("restore");
+}
+
+void TopLevelWindow::OnWindowResize() {
+  Emit("resize");
+}
+
+void TopLevelWindow::OnWindowMove() {
+  Emit("move");
+}
+
+void TopLevelWindow::OnWindowMoved() {
+  Emit("moved");
+}
+
+void TopLevelWindow::OnWindowEnterFullScreen() {
+  Emit("enter-full-screen");
+}
+
+void TopLevelWindow::OnWindowLeaveFullScreen() {
+  Emit("leave-full-screen");
+}
+
+void TopLevelWindow::OnWindowScrollTouchBegin() {
+  Emit("scroll-touch-begin");
+}
+
+void TopLevelWindow::OnWindowScrollTouchEnd() {
+  Emit("scroll-touch-end");
+}
+
+void TopLevelWindow::OnWindowSwipe(const std::string& direction) {
+  Emit("swipe", direction);
+}
+
+void TopLevelWindow::OnWindowSheetBegin() {
+  Emit("sheet-begin");
+}
+
+void TopLevelWindow::OnWindowSheetEnd() {
+  Emit("sheet-end");
+}
+
+void TopLevelWindow::OnWindowEnterHtmlFullScreen() {
+  Emit("enter-html-full-screen");
+}
+
+void TopLevelWindow::OnWindowLeaveHtmlFullScreen() {
+  Emit("leave-html-full-screen");
+}
+
+void TopLevelWindow::OnExecuteWindowsCommand(const std::string& command_name) {
+  Emit("app-command", command_name);
+}
+
+void TopLevelWindow::OnTouchBarItemResult(const std::string& item_id,
+                                  const base::DictionaryValue& details) {
+  Emit("-touch-bar-interaction", item_id, details);
+}
+
+void TopLevelWindow::OnNewWindowForTab() {
+  Emit("new-window-for-tab");
+}
+
+#if defined(OS_WIN)
+void TopLevelWindow::OnWindowMessage(UINT message,
+                                    WPARAM w_param,
+                                    LPARAM l_param) {
+  if (IsWindowMessageHooked(message)) {
+    messages_callback_map_[message].Run(
+        ToBuffer(isolate(), static_cast<void*>(&w_param), sizeof(WPARAM)),
+        ToBuffer(isolate(), static_cast<void*>(&l_param), sizeof(LPARAM)));
+  }
+}
+#endif
+
+void TopLevelWindow::Close() {
+  window_->Close();
+}
+
+void TopLevelWindow::Focus() {
+  window_->Focus(true);
+}
+
+void TopLevelWindow::Blur() {
+  window_->Focus(false);
+}
+
+bool TopLevelWindow::IsFocused() {
+  return window_->IsFocused();
+}
+
+void TopLevelWindow::Show() {
+  window_->Show();
+}
+
+void TopLevelWindow::ShowInactive() {
+  // This method doesn't make sense for modal window.
+  if (IsModal())
+    return;
+  window_->ShowInactive();
+}
+
+void TopLevelWindow::Hide() {
+  window_->Hide();
+}
+
+bool TopLevelWindow::IsVisible() {
+  return window_->IsVisible();
+}
+
+bool TopLevelWindow::IsEnabled() {
+  return window_->IsEnabled();
+}
+
+void TopLevelWindow::SetEnabled(bool enable) {
+  window_->SetEnabled(enable);
+}
+
+void TopLevelWindow::Maximize() {
+  window_->Maximize();
+}
+
+void TopLevelWindow::Unmaximize() {
+  window_->Unmaximize();
+}
+
+bool TopLevelWindow::IsMaximized() {
+  return window_->IsMaximized();
+}
+
+void TopLevelWindow::Minimize() {
+  window_->Minimize();
+}
+
+void TopLevelWindow::Restore() {
+  window_->Restore();
+}
+
+bool TopLevelWindow::IsMinimized() {
+  return window_->IsMinimized();
+}
+
+void TopLevelWindow::SetFullScreen(bool fullscreen) {
+  window_->SetFullScreen(fullscreen);
+}
+
+bool TopLevelWindow::IsFullscreen() {
+  return window_->IsFullscreen();
+}
+
+void TopLevelWindow::SetBounds(const gfx::Rect& bounds, mate::Arguments* args) {
+  bool animate = false;
+  args->GetNext(&animate);
+  window_->SetBounds(bounds, animate);
+}
+
+gfx::Rect TopLevelWindow::GetBounds() {
+  return window_->GetBounds();
+}
+
+void TopLevelWindow::SetContentBounds(const gfx::Rect& bounds,
+                                     mate::Arguments* args) {
+  bool animate = false;
+  args->GetNext(&animate);
+  window_->SetContentBounds(bounds, animate);
+}
+
+gfx::Rect TopLevelWindow::GetContentBounds() {
+  return window_->GetContentBounds();
+}
+
+void TopLevelWindow::SetSize(int width, int height, mate::Arguments* args) {
+  bool animate = false;
+  args->GetNext(&animate);
+  window_->SetSize(gfx::Size(width, height), animate);
+}
+
+std::vector<int> TopLevelWindow::GetSize() {
+  std::vector<int> result(2);
+  gfx::Size size = window_->GetSize();
+  result[0] = size.width();
+  result[1] = size.height();
+  return result;
+}
+
+void TopLevelWindow::SetContentSize(int width, int height,
+                                   mate::Arguments* args) {
+  bool animate = false;
+  args->GetNext(&animate);
+  window_->SetContentSize(gfx::Size(width, height), animate);
+}
+
+std::vector<int> TopLevelWindow::GetContentSize() {
+  std::vector<int> result(2);
+  gfx::Size size = window_->GetContentSize();
+  result[0] = size.width();
+  result[1] = size.height();
+  return result;
+}
+
+void TopLevelWindow::SetMinimumSize(int width, int height) {
+  window_->SetMinimumSize(gfx::Size(width, height));
+}
+
+std::vector<int> TopLevelWindow::GetMinimumSize() {
+  std::vector<int> result(2);
+  gfx::Size size = window_->GetMinimumSize();
+  result[0] = size.width();
+  result[1] = size.height();
+  return result;
+}
+
+void TopLevelWindow::SetMaximumSize(int width, int height) {
+  window_->SetMaximumSize(gfx::Size(width, height));
+}
+
+std::vector<int> TopLevelWindow::GetMaximumSize() {
+  std::vector<int> result(2);
+  gfx::Size size = window_->GetMaximumSize();
+  result[0] = size.width();
+  result[1] = size.height();
+  return result;
+}
+
+void TopLevelWindow::SetSheetOffset(double offsetY, mate::Arguments* args) {
+  double offsetX = 0.0;
+  args->GetNext(&offsetX);
+  window_->SetSheetOffset(offsetX, offsetY);
+}
+
+void TopLevelWindow::SetResizable(bool resizable) {
+  window_->SetResizable(resizable);
+}
+
+bool TopLevelWindow::IsResizable() {
+  return window_->IsResizable();
+}
+
+void TopLevelWindow::SetMovable(bool movable) {
+  window_->SetMovable(movable);
+}
+
+bool TopLevelWindow::IsMovable() {
+  return window_->IsMovable();
+}
+
+void TopLevelWindow::SetMinimizable(bool minimizable) {
+  window_->SetMinimizable(minimizable);
+}
+
+bool TopLevelWindow::IsMinimizable() {
+  return window_->IsMinimizable();
+}
+
+void TopLevelWindow::SetMaximizable(bool maximizable) {
+  window_->SetMaximizable(maximizable);
+}
+
+bool TopLevelWindow::IsMaximizable() {
+  return window_->IsMaximizable();
+}
+
+void TopLevelWindow::SetFullScreenable(bool fullscreenable) {
+  window_->SetFullScreenable(fullscreenable);
+}
+
+bool TopLevelWindow::IsFullScreenable() {
+  return window_->IsFullScreenable();
+}
+
+void TopLevelWindow::SetClosable(bool closable) {
+  window_->SetClosable(closable);
+}
+
+bool TopLevelWindow::IsClosable() {
+  return window_->IsClosable();
+}
+
+void TopLevelWindow::SetAlwaysOnTop(bool top, mate::Arguments* args) {
+  std::string level = "floating";
+  int relative_level = 0;
+  args->GetNext(&level);
+  args->GetNext(&relative_level);
+
+  std::string error;
+  window_->SetAlwaysOnTop(top, level, relative_level, &error);
+
+  if (!error.empty())
+    args->ThrowError(error);
+}
+
+bool TopLevelWindow::IsAlwaysOnTop() {
+  return window_->IsAlwaysOnTop();
+}
+
+void TopLevelWindow::Center() {
+  window_->Center();
+}
+
+void TopLevelWindow::SetPosition(int x, int y, mate::Arguments* args) {
+  bool animate = false;
+  args->GetNext(&animate);
+  window_->SetPosition(gfx::Point(x, y), animate);
+}
+
+std::vector<int> TopLevelWindow::GetPosition() {
+  std::vector<int> result(2);
+  gfx::Point pos = window_->GetPosition();
+  result[0] = pos.x();
+  result[1] = pos.y();
+  return result;
+}
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+void TopLevelWindow::MoveTop() {
+  window_->MoveTop();
+}
+#endif
+
+void TopLevelWindow::SetTitle(const std::string& title) {
+  window_->SetTitle(title);
+}
+
+std::string TopLevelWindow::GetTitle() {
+  return window_->GetTitle();
+}
+
+void TopLevelWindow::FlashFrame(bool flash) {
+  window_->FlashFrame(flash);
+}
+
+void TopLevelWindow::SetSkipTaskbar(bool skip) {
+  window_->SetSkipTaskbar(skip);
+}
+
+void TopLevelWindow::SetSimpleFullScreen(bool simple_fullscreen) {
+  window_->SetSimpleFullScreen(simple_fullscreen);
+}
+
+bool TopLevelWindow::IsSimpleFullScreen() {
+  return window_->IsSimpleFullScreen();
+}
+
+void TopLevelWindow::SetKiosk(bool kiosk) {
+  window_->SetKiosk(kiosk);
+}
+
+bool TopLevelWindow::IsKiosk() {
+  return window_->IsKiosk();
+}
+
+void TopLevelWindow::SetBackgroundColor(const std::string& color_name) {
+  SkColor color = ParseHexColor(color_name);
+  window_->SetBackgroundColor(color);
+}
+
+void TopLevelWindow::SetHasShadow(bool has_shadow) {
+  window_->SetHasShadow(has_shadow);
+}
+
+bool TopLevelWindow::HasShadow() {
+  return window_->HasShadow();
+}
+
+void TopLevelWindow::SetOpacity(const double opacity) {
+  window_->SetOpacity(opacity);
+}
+
+double TopLevelWindow::GetOpacity() {
+  return window_->GetOpacity();
+}
+
+void TopLevelWindow::SetRepresentedFilename(const std::string& filename) {
+  window_->SetRepresentedFilename(filename);
+}
+
+std::string TopLevelWindow::GetRepresentedFilename() {
+  return window_->GetRepresentedFilename();
+}
+
+void TopLevelWindow::SetDocumentEdited(bool edited) {
+  window_->SetDocumentEdited(edited);
+}
+
+bool TopLevelWindow::IsDocumentEdited() {
+  return window_->IsDocumentEdited();
+}
+
+void TopLevelWindow::SetIgnoreMouseEvents(bool ignore, mate::Arguments* args) {
+  mate::Dictionary options;
+  bool forward = false;
+  args->GetNext(&options) && options.Get("forward", &forward);
+  return window_->SetIgnoreMouseEvents(ignore, forward);
+}
+
+void TopLevelWindow::SetContentProtection(bool enable) {
+  return window_->SetContentProtection(enable);
+}
+
+void TopLevelWindow::SetFocusable(bool focusable) {
+  return window_->SetFocusable(focusable);
+}
+
+void TopLevelWindow::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
+  mate::Handle<Menu> menu;
+  if (value->IsObject() &&
+      mate::V8ToString(value->ToObject()->GetConstructorName()) == "Menu" &&
+      mate::ConvertFromV8(isolate, value, &menu) &&
+      !menu.IsEmpty()) {
+    menu_.Reset(isolate, menu.ToV8());
+    window_->SetMenu(menu->model());
+  } else if (value->IsNull()) {
+    menu_.Reset();
+    window_->SetMenu(nullptr);
+  } else {
+    isolate->ThrowException(v8::Exception::TypeError(
+        mate::StringToV8(isolate, "Invalid Menu")));
+  }
+}
+
+void TopLevelWindow::SetParentWindow(v8::Local<v8::Value> value,
+                                     mate::Arguments* args) {
+  if (IsModal()) {
+    args->ThrowError("Can not be called for modal window");
+    return;
+  }
+
+  mate::Handle<TopLevelWindow> parent;
+  if (value->IsNull() || value->IsUndefined()) {
+    RemoveFromParentChildWindows();
+    parent_window_.Reset();
+    window_->SetParentWindow(nullptr);
+  } else if (mate::ConvertFromV8(isolate(), value, &parent)) {
+    parent_window_.Reset(isolate(), value);
+    window_->SetParentWindow(parent->window_.get());
+    parent->child_windows_.Set(isolate(), weak_map_id(), GetWrapper());
+  } else {
+    args->ThrowError("Must pass TopLevelWindow instance or null");
+  }
+}
+
+void TopLevelWindow::SetBrowserView(v8::Local<v8::Value> value) {
+  ResetBrowserView();
+
+  mate::Handle<BrowserView> browser_view;
+  if (value->IsNull() || value->IsUndefined()) {
+    window_->SetBrowserView(nullptr);
+  } else if (mate::ConvertFromV8(isolate(), value, &browser_view)) {
+    window_->SetBrowserView(browser_view->view());
+    browser_view->web_contents()->SetOwnerWindow(window_.get());
+    browser_view_.Reset(isolate(), value);
+  }
+}
+
+v8::Local<v8::Value> TopLevelWindow::GetNativeWindowHandle() {
+  gfx::AcceleratedWidget handle = window_->GetAcceleratedWidget();
+  return ToBuffer(isolate(), static_cast<void*>(&handle), sizeof(handle));
+}
+
+void TopLevelWindow::SetProgressBar(double progress, mate::Arguments* args) {
+  mate::Dictionary options;
+  std::string mode;
+  args->GetNext(&options) && options.Get("mode", &mode);
+
+  NativeWindow::ProgressState state = NativeWindow::PROGRESS_NORMAL;
+  if (mode == "error")
+    state = NativeWindow::PROGRESS_ERROR;
+  else if (mode == "paused")
+    state = NativeWindow::PROGRESS_PAUSED;
+  else if (mode == "indeterminate")
+    state = NativeWindow::PROGRESS_INDETERMINATE;
+  else if (mode == "none")
+    state = NativeWindow::PROGRESS_NONE;
+
+  window_->SetProgressBar(progress, state);
+}
+
+void TopLevelWindow::SetOverlayIcon(const gfx::Image& overlay,
+                                    const std::string& description) {
+  window_->SetOverlayIcon(overlay, description);
+}
+
+void TopLevelWindow::SetVisibleOnAllWorkspaces(bool visible) {
+  return window_->SetVisibleOnAllWorkspaces(visible);
+}
+
+bool TopLevelWindow::IsVisibleOnAllWorkspaces() {
+  return window_->IsVisibleOnAllWorkspaces();
+}
+
+void TopLevelWindow::SetAutoHideCursor(bool auto_hide) {
+  window_->SetAutoHideCursor(auto_hide);
+}
+
+void TopLevelWindow::SetVibrancy(mate::Arguments* args) {
+  std::string type;
+  args->GetNext(&type);
+  window_->SetVibrancy(type);
+}
+
+void TopLevelWindow::SetTouchBar(
+    const std::vector<mate::PersistentDictionary>& items) {
+  window_->SetTouchBar(items);
+}
+
+void TopLevelWindow::RefreshTouchBarItem(const std::string& item_id) {
+  window_->RefreshTouchBarItem(item_id);
+}
+
+void TopLevelWindow::SetEscapeTouchBarItem(
+    const mate::PersistentDictionary& item) {
+  window_->SetEscapeTouchBarItem(item);
+}
+
+void TopLevelWindow::SelectPreviousTab() {
+  window_->SelectPreviousTab();
+}
+
+void TopLevelWindow::SelectNextTab() {
+  window_->SelectNextTab();
+}
+
+void TopLevelWindow::MergeAllWindows() {
+  window_->MergeAllWindows();
+}
+
+void TopLevelWindow::MoveTabToNewWindow() {
+  window_->MoveTabToNewWindow();
+}
+
+void TopLevelWindow::ToggleTabBar() {
+  window_->ToggleTabBar();
+}
+
+void TopLevelWindow::AddTabbedWindow(NativeWindow* window,
+                                     mate::Arguments* args) {
+  if (!window_->AddTabbedWindow(window))
+    args->ThrowError("AddTabbedWindow cannot be called by a window on itself.");
+}
+
+void TopLevelWindow::SetAutoHideMenuBar(bool auto_hide) {
+  window_->SetAutoHideMenuBar(auto_hide);
+}
+
+bool TopLevelWindow::IsMenuBarAutoHide() {
+  return window_->IsMenuBarAutoHide();
+}
+
+void TopLevelWindow::SetMenuBarVisibility(bool visible) {
+  window_->SetMenuBarVisibility(visible);
+}
+
+bool TopLevelWindow::IsMenuBarVisible() {
+  return window_->IsMenuBarVisible();
+}
+
+void TopLevelWindow::SetAspectRatio(double aspect_ratio,
+                                    mate::Arguments* args) {
+  gfx::Size extra_size;
+  args->GetNext(&extra_size);
+  window_->SetAspectRatio(aspect_ratio, extra_size);
+}
+
+void TopLevelWindow::PreviewFile(const std::string& path,
+                                 mate::Arguments* args) {
+  std::string display_name;
+  if (!args->GetNext(&display_name))
+    display_name = path;
+  window_->PreviewFile(path, display_name);
+}
+
+void TopLevelWindow::CloseFilePreview() {
+  window_->CloseFilePreview();
+}
+
+v8::Local<v8::Value> TopLevelWindow::GetParentWindow() const {
+  if (parent_window_.IsEmpty())
+    return v8::Null(isolate());
+  else
+    return v8::Local<v8::Value>::New(isolate(), parent_window_);
+}
+
+std::vector<v8::Local<v8::Object>> TopLevelWindow::GetChildWindows() const {
+  return child_windows_.Values(isolate());
+}
+
+v8::Local<v8::Value> TopLevelWindow::GetBrowserView() const {
+  if (browser_view_.IsEmpty()) {
+    return v8::Null(isolate());
+  }
+
+  return v8::Local<v8::Value>::New(isolate(), browser_view_);
+}
+
+bool TopLevelWindow::IsModal() const {
+  return window_->is_modal();
+}
+
+bool TopLevelWindow::SetThumbarButtons(mate::Arguments* args) {
+#if defined(OS_WIN)
+  std::vector<TaskbarHost::ThumbarButton> buttons;
+  if (!args->GetNext(&buttons)) {
+    args->ThrowError();
+    return false;
+  }
+  auto window = static_cast<NativeWindowViews*>(window_.get());
+  return window->taskbar_host().SetThumbarButtons(
+      window_->GetAcceleratedWidget(), buttons);
+#else
+  return false;
+#endif
+}
+
+#if defined(TOOLKIT_VIEWS)
+void TopLevelWindow::SetIcon(mate::Handle<NativeImage> icon) {
+#if defined(OS_WIN)
+  static_cast<NativeWindowViews*>(window_.get())->SetIcon(
+      icon->GetHICON(GetSystemMetrics(SM_CXSMICON)),
+      icon->GetHICON(GetSystemMetrics(SM_CXICON)));
+#elif defined(USE_X11)
+  static_cast<NativeWindowViews*>(window_.get())->SetIcon(
+      icon->image().AsImageSkia());
+#endif
+}
+#endif
+
+#if defined(OS_WIN)
+bool TopLevelWindow::HookWindowMessage(UINT message,
+                               const MessageCallback& callback) {
+  messages_callback_map_[message] = callback;
+  return true;
+}
+
+void TopLevelWindow::UnhookWindowMessage(UINT message) {
+  if (!ContainsKey(messages_callback_map_, message))
+    return;
+
+  messages_callback_map_.erase(message);
+}
+
+bool TopLevelWindow::IsWindowMessageHooked(UINT message) {
+  return ContainsKey(messages_callback_map_, message);
+}
+
+void TopLevelWindow::UnhookAllWindowMessages() {
+  messages_callback_map_.clear();
+}
+
+bool TopLevelWindow::SetThumbnailClip(const gfx::Rect& region) {
+  auto* window = static_cast<NativeWindowViews*>(window_.get());
+  return window->taskbar_host().SetThumbnailClip(
+      window_->GetAcceleratedWidget(), region);
+}
+
+bool TopLevelWindow::SetThumbnailToolTip(const std::string& tooltip) {
+  auto* window = static_cast<NativeWindowViews*>(window_.get());
+  return window->taskbar_host().SetThumbnailToolTip(
+      window_->GetAcceleratedWidget(), tooltip);
+}
+
+void TopLevelWindow::SetAppDetails(const mate::Dictionary& options) {
+  base::string16 app_id;
+  base::FilePath app_icon_path;
+  int app_icon_index = 0;
+  base::string16 relaunch_command;
+  base::string16 relaunch_display_name;
+
+  options.Get("appId", &app_id);
+  options.Get("appIconPath", &app_icon_path);
+  options.Get("appIconIndex", &app_icon_index);
+  options.Get("relaunchCommand", &relaunch_command);
+  options.Get("relaunchDisplayName", &relaunch_display_name);
+
+  ui::win::SetAppDetailsForWindow(
+      app_id, app_icon_path, app_icon_index,
+      relaunch_command, relaunch_display_name,
+      window_->GetAcceleratedWidget());
+}
+#endif
+
+int32_t TopLevelWindow::GetID() const {
+  return weak_map_id();
+}
+
+void TopLevelWindow::ResetBrowserView() {
+  if (browser_view_.IsEmpty())
+    return;
+
+  mate::Handle<BrowserView> browser_view;
+  if (mate::ConvertFromV8(isolate(), GetBrowserView(), &browser_view) &&
+      !browser_view.IsEmpty()) {
+    browser_view->web_contents()->SetOwnerWindow(nullptr);
+  }
+
+  browser_view_.Reset();
+}
+
+void TopLevelWindow::RemoveFromParentChildWindows() {
+  if (parent_window_.IsEmpty())
+    return;
+
+  mate::Handle<TopLevelWindow> parent;
+  if (!mate::ConvertFromV8(isolate(), GetParentWindow(), &parent) ||
+      parent.IsEmpty()) {
+    return;
+  }
+
+  parent->child_windows_.Remove(weak_map_id());
+}
+
+// static
+mate::WrappableBase* TopLevelWindow::New(mate::Arguments* args) {
+  mate::Dictionary options;
+  if (!(args->Length() == 1 && args->GetNext(&options)))
+    options = mate::Dictionary::CreateEmpty(args->isolate());
+  return new TopLevelWindow(args->isolate(), args->GetThis(), options);
+}
+
+// static
+void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
+                                    v8::Local<v8::FunctionTemplate> prototype) {
+  prototype->SetClassName(mate::StringToV8(isolate, "TopLevelWindow"));
+  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
+      .MakeDestroyable()
+      .SetMethod("close", &TopLevelWindow::Close)
+      .SetMethod("focus", &TopLevelWindow::Focus)
+      .SetMethod("blur", &TopLevelWindow::Blur)
+      .SetMethod("isFocused", &TopLevelWindow::IsFocused)
+      .SetMethod("show", &TopLevelWindow::Show)
+      .SetMethod("showInactive", &TopLevelWindow::ShowInactive)
+      .SetMethod("hide", &TopLevelWindow::Hide)
+      .SetMethod("isVisible", &TopLevelWindow::IsVisible)
+      .SetMethod("isEnabled", &TopLevelWindow::IsEnabled)
+      .SetMethod("setEnabled", & TopLevelWindow::SetEnabled)
+      .SetMethod("maximize", &TopLevelWindow::Maximize)
+      .SetMethod("unmaximize", &TopLevelWindow::Unmaximize)
+      .SetMethod("isMaximized", &TopLevelWindow::IsMaximized)
+      .SetMethod("minimize", &TopLevelWindow::Minimize)
+      .SetMethod("restore", &TopLevelWindow::Restore)
+      .SetMethod("isMinimized", &TopLevelWindow::IsMinimized)
+      .SetMethod("setFullScreen", &TopLevelWindow::SetFullScreen)
+      .SetMethod("isFullScreen", &TopLevelWindow::IsFullscreen)
+      .SetMethod("setBounds", &TopLevelWindow::SetBounds)
+      .SetMethod("getBounds", &TopLevelWindow::GetBounds)
+      .SetMethod("setSize", &TopLevelWindow::SetSize)
+      .SetMethod("getSize", &TopLevelWindow::GetSize)
+      .SetMethod("setContentBounds", &TopLevelWindow::SetContentBounds)
+      .SetMethod("getContentBounds", &TopLevelWindow::GetContentBounds)
+      .SetMethod("setContentSize", &TopLevelWindow::SetContentSize)
+      .SetMethod("getContentSize", &TopLevelWindow::GetContentSize)
+      .SetMethod("setMinimumSize", &TopLevelWindow::SetMinimumSize)
+      .SetMethod("getMinimumSize", &TopLevelWindow::GetMinimumSize)
+      .SetMethod("setMaximumSize", &TopLevelWindow::SetMaximumSize)
+      .SetMethod("getMaximumSize", &TopLevelWindow::GetMaximumSize)
+      .SetMethod("setSheetOffset", &TopLevelWindow::SetSheetOffset)
+      .SetMethod("setResizable", &TopLevelWindow::SetResizable)
+      .SetMethod("isResizable", &TopLevelWindow::IsResizable)
+      .SetMethod("setMovable", &TopLevelWindow::SetMovable)
+#if defined(OS_WIN) || defined(OS_MACOSX)
+      .SetMethod("moveTop" , &TopLevelWindow::MoveTop)
+#endif
+      .SetMethod("isMovable", &TopLevelWindow::IsMovable)
+      .SetMethod("setMinimizable", &TopLevelWindow::SetMinimizable)
+      .SetMethod("isMinimizable", &TopLevelWindow::IsMinimizable)
+      .SetMethod("setMaximizable", &TopLevelWindow::SetMaximizable)
+      .SetMethod("isMaximizable", &TopLevelWindow::IsMaximizable)
+      .SetMethod("setFullScreenable", &TopLevelWindow::SetFullScreenable)
+      .SetMethod("isFullScreenable", &TopLevelWindow::IsFullScreenable)
+      .SetMethod("setClosable", &TopLevelWindow::SetClosable)
+      .SetMethod("isClosable", &TopLevelWindow::IsClosable)
+      .SetMethod("setAlwaysOnTop", &TopLevelWindow::SetAlwaysOnTop)
+      .SetMethod("isAlwaysOnTop", &TopLevelWindow::IsAlwaysOnTop)
+      .SetMethod("center", &TopLevelWindow::Center)
+      .SetMethod("setPosition", &TopLevelWindow::SetPosition)
+      .SetMethod("getPosition", &TopLevelWindow::GetPosition)
+      .SetMethod("setTitle", &TopLevelWindow::SetTitle)
+      .SetMethod("getTitle", &TopLevelWindow::GetTitle)
+      .SetMethod("flashFrame", &TopLevelWindow::FlashFrame)
+      .SetMethod("setSkipTaskbar", &TopLevelWindow::SetSkipTaskbar)
+      .SetMethod("setSimpleFullScreen", &TopLevelWindow::SetSimpleFullScreen)
+      .SetMethod("isSimpleFullScreen", &TopLevelWindow::IsSimpleFullScreen)
+      .SetMethod("setKiosk", &TopLevelWindow::SetKiosk)
+      .SetMethod("isKiosk", &TopLevelWindow::IsKiosk)
+      .SetMethod("setBackgroundColor", &TopLevelWindow::SetBackgroundColor)
+      .SetMethod("setHasShadow", &TopLevelWindow::SetHasShadow)
+      .SetMethod("hasShadow", &TopLevelWindow::HasShadow)
+      .SetMethod("setOpacity", &TopLevelWindow::SetOpacity)
+      .SetMethod("getOpacity", &TopLevelWindow::GetOpacity)
+      .SetMethod("setRepresentedFilename",
+                 &TopLevelWindow::SetRepresentedFilename)
+      .SetMethod("getRepresentedFilename",
+                 &TopLevelWindow::GetRepresentedFilename)
+      .SetMethod("setDocumentEdited", &TopLevelWindow::SetDocumentEdited)
+      .SetMethod("isDocumentEdited", &TopLevelWindow::IsDocumentEdited)
+      .SetMethod("setIgnoreMouseEvents", &TopLevelWindow::SetIgnoreMouseEvents)
+      .SetMethod("setContentProtection", &TopLevelWindow::SetContentProtection)
+      .SetMethod("setFocusable", &TopLevelWindow::SetFocusable)
+      .SetMethod("setMenu", &TopLevelWindow::SetMenu)
+#if !defined(OS_WIN)
+      .SetMethod("setParentWindow", &TopLevelWindow::SetParentWindow)
+#endif
+      .SetMethod("setBrowserView", &TopLevelWindow::SetBrowserView)
+      .SetMethod("getNativeWindowHandle",
+                 &TopLevelWindow::GetNativeWindowHandle)
+      .SetMethod("setProgressBar", &TopLevelWindow::SetProgressBar)
+      .SetMethod("setOverlayIcon", &TopLevelWindow::SetOverlayIcon)
+      .SetMethod("setVisibleOnAllWorkspaces",
+                 &TopLevelWindow::SetVisibleOnAllWorkspaces)
+      .SetMethod("isVisibleOnAllWorkspaces",
+                 &TopLevelWindow::IsVisibleOnAllWorkspaces)
+#if defined(OS_MACOSX)
+      .SetMethod("setAutoHideCursor", &TopLevelWindow::SetAutoHideCursor)
+#endif
+      .SetMethod("setVibrancy", &TopLevelWindow::SetVibrancy)
+      .SetMethod("_setTouchBarItems", &TopLevelWindow::SetTouchBar)
+      .SetMethod("_refreshTouchBarItem", &TopLevelWindow::RefreshTouchBarItem)
+      .SetMethod("_setEscapeTouchBarItem",
+                 &TopLevelWindow::SetEscapeTouchBarItem)
+#if defined(OS_MACOSX)
+      .SetMethod("selectPreviousTab", &TopLevelWindow::SelectPreviousTab)
+      .SetMethod("selectNextTab", &TopLevelWindow::SelectNextTab)
+      .SetMethod("mergeAllWindows", &TopLevelWindow::MergeAllWindows)
+      .SetMethod("moveTabToNewWindow", &TopLevelWindow::MoveTabToNewWindow)
+      .SetMethod("toggleTabBar", &TopLevelWindow::ToggleTabBar)
+      .SetMethod("addTabbedWindow", &TopLevelWindow::AddTabbedWindow)
+#endif
+      .SetMethod("setAutoHideMenuBar", &TopLevelWindow::SetAutoHideMenuBar)
+      .SetMethod("isMenuBarAutoHide", &TopLevelWindow::IsMenuBarAutoHide)
+      .SetMethod("setMenuBarVisibility", &TopLevelWindow::SetMenuBarVisibility)
+      .SetMethod("isMenuBarVisible", &TopLevelWindow::IsMenuBarVisible)
+      .SetMethod("setAspectRatio", &TopLevelWindow::SetAspectRatio)
+      .SetMethod("previewFile", &TopLevelWindow::PreviewFile)
+      .SetMethod("closeFilePreview", &TopLevelWindow::CloseFilePreview)
+      .SetMethod("getParentWindow", &TopLevelWindow::GetParentWindow)
+      .SetMethod("getChildWindows", &TopLevelWindow::GetChildWindows)
+      .SetMethod("getBrowserView", &TopLevelWindow::GetBrowserView)
+      .SetMethod("isModal", &TopLevelWindow::IsModal)
+      .SetMethod("setThumbarButtons", &TopLevelWindow::SetThumbarButtons)
+#if defined(TOOLKIT_VIEWS)
+      .SetMethod("setIcon", &TopLevelWindow::SetIcon)
+#endif
+#if defined(OS_WIN)
+      .SetMethod("hookWindowMessage", &TopLevelWindow::HookWindowMessage)
+      .SetMethod("isWindowMessageHooked",
+                 &TopLevelWindow::IsWindowMessageHooked)
+      .SetMethod("unhookWindowMessage", &TopLevelWindow::UnhookWindowMessage)
+      .SetMethod("unhookAllWindowMessages",
+                 &TopLevelWindow::UnhookAllWindowMessages)
+      .SetMethod("setThumbnailClip", &TopLevelWindow::SetThumbnailClip)
+      .SetMethod("setThumbnailToolTip", &TopLevelWindow::SetThumbnailToolTip)
+      .SetMethod("setAppDetails", &TopLevelWindow::SetAppDetails)
+#endif
+      .SetProperty("id", &TopLevelWindow::GetID);
+}
+
+}  // namespace api
+
+}  // namespace atom
+
+namespace {
+
+using atom::api::TopLevelWindow;
+
+void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
+                v8::Local<v8::Context> context, void* priv) {
+  v8::Isolate* isolate = context->GetIsolate();
+  TopLevelWindow::SetConstructor(isolate, base::Bind(&TopLevelWindow::New));
+
+  mate::Dictionary constructor(
+      isolate, TopLevelWindow::GetConstructor(isolate)->GetFunction());
+  constructor.SetMethod("fromId",
+                        &mate::TrackableObject<TopLevelWindow>::FromWeakMapID);
+  constructor.SetMethod("getAllWindows",
+                        &mate::TrackableObject<TopLevelWindow>::GetAll);
+
+  mate::Dictionary dict(isolate, exports);
+  dict.Set("TopLevelWindow", constructor);
+}
+
+}  // namespace
+
+NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_top_level_window, Initialize)

+ 226 - 0
atom/browser/api/atom_api_top_level_window.h

@@ -0,0 +1,226 @@
+// Copyright (c) 2018 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_API_ATOM_API_TOP_LEVEL_WINDOW_H_
+#define ATOM_BROWSER_API_ATOM_API_TOP_LEVEL_WINDOW_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "atom/browser/api/trackable_object.h"
+#include "atom/browser/native_window.h"
+#include "atom/browser/native_window_observer.h"
+#include "atom/common/api/atom_api_native_image.h"
+#include "native_mate/handle.h"
+
+namespace atom {
+
+namespace api {
+
+class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
+                       public NativeWindowObserver {
+ public:
+  static mate::WrappableBase* New(mate::Arguments* args);
+
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::FunctionTemplate> prototype);
+
+  base::WeakPtr<TopLevelWindow> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
+  NativeWindow* window() const { return window_.get(); }
+
+ protected:
+  TopLevelWindow(v8::Isolate* isolate,
+                 v8::Local<v8::Object> wrapper,
+                 const mate::Dictionary& options);
+  ~TopLevelWindow() override;
+
+  // NativeWindowObserver:
+  void WillCloseWindow(bool* prevent_default) override;
+  void OnWindowClosed() override;
+  void OnWindowEndSession() override;
+  void OnWindowBlur() override;
+  void OnWindowFocus() override;
+  void OnWindowShow() override;
+  void OnWindowHide() override;
+  void OnWindowMaximize() override;
+  void OnWindowUnmaximize() override;
+  void OnWindowMinimize() override;
+  void OnWindowRestore() override;
+  void OnWindowResize() override;
+  void OnWindowMove() override;
+  void OnWindowMoved() override;
+  void OnWindowScrollTouchBegin() override;
+  void OnWindowScrollTouchEnd() override;
+  void OnWindowSwipe(const std::string& direction) override;
+  void OnWindowSheetBegin() override;
+  void OnWindowSheetEnd() override;
+  void OnWindowEnterFullScreen() override;
+  void OnWindowLeaveFullScreen() override;
+  void OnWindowEnterHtmlFullScreen() override;
+  void OnWindowLeaveHtmlFullScreen() override;
+  void OnExecuteWindowsCommand(const std::string& command_name) override;
+  void OnTouchBarItemResult(const std::string& item_id,
+                            const base::DictionaryValue& details) override;
+  void OnNewWindowForTab() override;
+  #if defined(OS_WIN)
+  void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
+  #endif
+
+  // Public APIs of NativeWindow.
+  void Close();
+  virtual void Focus();
+  virtual void Blur();
+  bool IsFocused();
+  void Show();
+  void ShowInactive();
+  void Hide();
+  bool IsVisible();
+  bool IsEnabled();
+  void SetEnabled(bool enable);
+  void Maximize();
+  void Unmaximize();
+  bool IsMaximized();
+  void Minimize();
+  void Restore();
+  bool IsMinimized();
+  void SetFullScreen(bool fullscreen);
+  bool IsFullscreen();
+  void SetBounds(const gfx::Rect& bounds, mate::Arguments* args);
+  gfx::Rect GetBounds();
+  void SetSize(int width, int height, mate::Arguments* args);
+  std::vector<int> GetSize();
+  void SetContentSize(int width, int height, mate::Arguments* args);
+  std::vector<int> GetContentSize();
+  void SetContentBounds(const gfx::Rect& bounds, mate::Arguments* args);
+  gfx::Rect GetContentBounds();
+  void SetMinimumSize(int width, int height);
+  std::vector<int> GetMinimumSize();
+  void SetMaximumSize(int width, int height);
+  std::vector<int> GetMaximumSize();
+  void SetSheetOffset(double offsetY, mate::Arguments* args);
+  void SetResizable(bool resizable);
+  bool IsResizable();
+  void SetMovable(bool movable);
+  #if defined(OS_WIN) || defined(OS_MACOSX)
+  void MoveTop();
+  #endif
+  bool IsMovable();
+  void SetMinimizable(bool minimizable);
+  bool IsMinimizable();
+  void SetMaximizable(bool maximizable);
+  bool IsMaximizable();
+  void SetFullScreenable(bool fullscreenable);
+  bool IsFullScreenable();
+  void SetClosable(bool closable);
+  bool IsClosable();
+  void SetAlwaysOnTop(bool top, mate::Arguments* args);
+  bool IsAlwaysOnTop();
+  void Center();
+  void SetPosition(int x, int y, mate::Arguments* args);
+  std::vector<int> GetPosition();
+  void SetTitle(const std::string& title);
+  std::string GetTitle();
+  void FlashFrame(bool flash);
+  void SetSkipTaskbar(bool skip);
+  void SetSimpleFullScreen(bool simple_fullscreen);
+  bool IsSimpleFullScreen();
+  void SetKiosk(bool kiosk);
+  bool IsKiosk();
+  virtual void SetBackgroundColor(const std::string& color_name);
+  void SetHasShadow(bool has_shadow);
+  bool HasShadow();
+  void SetOpacity(const double opacity);
+  double GetOpacity();
+  void SetRepresentedFilename(const std::string& filename);
+  std::string GetRepresentedFilename();
+  void SetDocumentEdited(bool edited);
+  bool IsDocumentEdited();
+  void SetIgnoreMouseEvents(bool ignore, mate::Arguments* args);
+  void SetContentProtection(bool enable);
+  void SetFocusable(bool focusable);
+  void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
+  void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
+  virtual void SetBrowserView(v8::Local<v8::Value> value);
+  v8::Local<v8::Value> GetNativeWindowHandle();
+  void SetProgressBar(double progress, mate::Arguments* args);
+  void SetOverlayIcon(const gfx::Image& overlay,
+                      const std::string& description);
+  void SetVisibleOnAllWorkspaces(bool visible);
+  bool IsVisibleOnAllWorkspaces();
+  void SetAutoHideCursor(bool auto_hide);
+  virtual void SetVibrancy(mate::Arguments* args);
+  void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
+  void RefreshTouchBarItem(const std::string& item_id);
+  void SetEscapeTouchBarItem(const mate::PersistentDictionary& item);
+  void SelectPreviousTab();
+  void SelectNextTab();
+  void MergeAllWindows();
+  void MoveTabToNewWindow();
+  void ToggleTabBar();
+  void AddTabbedWindow(NativeWindow* window, mate::Arguments* args);
+  void SetAutoHideMenuBar(bool auto_hide);
+  bool IsMenuBarAutoHide();
+  void SetMenuBarVisibility(bool visible);
+  bool IsMenuBarVisible();
+  void SetAspectRatio(double aspect_ratio, mate::Arguments* args);
+  void PreviewFile(const std::string& path, mate::Arguments* args);
+  void CloseFilePreview();
+
+  // Public getters of NativeWindow.
+  v8::Local<v8::Value> GetParentWindow() const;
+  std::vector<v8::Local<v8::Object>> GetChildWindows() const;
+  v8::Local<v8::Value> GetBrowserView() const;
+  bool IsModal() const;
+
+  // Extra APIs added in JS.
+  bool SetThumbarButtons(mate::Arguments* args);
+#if defined(TOOLKIT_VIEWS)
+  void SetIcon(mate::Handle<NativeImage> icon);
+#endif
+#if defined(OS_WIN)
+  typedef base::Callback<void(v8::Local<v8::Value>,
+                              v8::Local<v8::Value>)> MessageCallback;
+  bool HookWindowMessage(UINT message, const MessageCallback& callback);
+  bool IsWindowMessageHooked(UINT message);
+  void UnhookWindowMessage(UINT message);
+  void UnhookAllWindowMessages();
+  bool SetThumbnailClip(const gfx::Rect& region);
+  bool SetThumbnailToolTip(const std::string& tooltip);
+  void SetAppDetails(const mate::Dictionary& options);
+#endif
+  int32_t GetID() const;
+
+  // Helpers.
+
+  // Remove BrowserView.
+  void ResetBrowserView();
+
+  // Remove this window from parent window's |child_windows_|.
+  void RemoveFromParentChildWindows();
+
+#if defined(OS_WIN)
+  typedef std::map<UINT, MessageCallback> MessageCallbackMap;
+  MessageCallbackMap messages_callback_map_;
+#endif
+
+  v8::Global<v8::Value> browser_view_;
+  v8::Global<v8::Value> menu_;
+  v8::Global<v8::Value> parent_window_;
+  KeyWeakMap<int> child_windows_;
+
+  std::unique_ptr<NativeWindow> window_;
+
+  base::WeakPtrFactory<TopLevelWindow> weak_factory_;
+};
+
+}  // namespace api
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_API_ATOM_API_TOP_LEVEL_WINDOW_H_

+ 1 - 0
atom/browser/api/atom_api_web_contents.cc

@@ -29,6 +29,7 @@
 #include "atom/browser/web_contents_zoom_controller.h"
 #include "atom/browser/web_view_guest_delegate.h"
 #include "atom/common/api/api_messages.h"
+#include "atom/common/api/atom_api_native_image.h"
 #include "atom/common/api/event_emitter_caller.h"
 #include "atom/common/color_util.h"
 #include "atom/common/mouse_util.h"

+ 3 - 2
atom/browser/api/trackable_object.h

@@ -107,7 +107,9 @@ class TrackableObject : public TrackableObjectBase,
   }
 
  protected:
-  TrackableObject() {}
+  TrackableObject() {
+    weak_map_id_ = ++next_id_;
+  }
 
   ~TrackableObject() override {
     RemoveFromWeakMap();
@@ -118,7 +120,6 @@ class TrackableObject : public TrackableObjectBase,
     if (!weak_map_) {
       weak_map_ = new atom::KeyWeakMap<int32_t>;
     }
-    weak_map_id_ = ++next_id_;
     weak_map_->Set(isolate, weak_map_id_, wrapper);
   }
 

+ 1 - 0
atom/common/node_bindings.cc

@@ -46,6 +46,7 @@
   V(atom_browser_render_process_preferences) \
   V(atom_browser_session)                    \
   V(atom_browser_system_preferences)         \
+  V(atom_browser_top_level_window)           \
   V(atom_browser_tray)                       \
   V(atom_browser_web_contents)               \
   V(atom_browser_web_view_manager)           \

+ 2 - 0
filenames.gypi

@@ -152,6 +152,8 @@
       'atom/browser/api/atom_api_system_preferences.h',
       'atom/browser/api/atom_api_system_preferences_mac.mm',
       'atom/browser/api/atom_api_system_preferences_win.cc',
+      'atom/browser/api/atom_api_top_level_window.cc',
+      'atom/browser/api/atom_api_top_level_window.h',
       'atom/browser/api/atom_api_tray.cc',
       'atom/browser/api/atom_api_tray.h',
       'atom/browser/api/atom_api_url_request.cc',

Some files were not shown because too many files changed in this diff