Browse Source

Merge branch 'master' into chrome52

Cheng Zhao 8 years ago
parent
commit
b57665330c
100 changed files with 948 additions and 468 deletions
  1. 1 1
      .node-version
  2. 1 0
      README-ko.md
  3. 1 0
      README.md
  4. 3 2
      atom/app/node_main.cc
  5. 1 1
      atom/app/uv_task_runner.cc
  6. 41 1
      atom/browser/api/atom_api_app.cc
  7. 2 0
      atom/browser/api/atom_api_app.h
  8. 1 0
      atom/browser/api/atom_api_auto_updater.cc
  9. 1 0
      atom/browser/api/atom_api_auto_updater.h
  10. 7 4
      atom/browser/api/atom_api_menu.cc
  11. 5 3
      atom/browser/api/atom_api_menu.h
  12. 8 2
      atom/browser/api/atom_api_menu_mac.mm
  13. 4 0
      atom/browser/api/atom_api_menu_views.cc
  14. 26 1
      atom/browser/api/atom_api_protocol.cc
  15. 1 0
      atom/browser/api/atom_api_protocol.h
  16. 56 17
      atom/browser/api/atom_api_session.cc
  17. 4 2
      atom/browser/api/atom_api_session.h
  18. 6 0
      atom/browser/api/atom_api_tray.cc
  19. 1 0
      atom/browser/api/atom_api_tray.h
  20. 84 32
      atom/browser/api/atom_api_web_contents.cc
  21. 7 8
      atom/browser/api/atom_api_web_contents.h
  22. 30 0
      atom/browser/api/atom_api_web_contents_mac.mm
  23. 7 25
      atom/browser/api/atom_api_window.cc
  24. 1 1
      atom/browser/api/atom_api_window.h
  25. 7 7
      atom/browser/api/event.cc
  26. 2 3
      atom/browser/atom_access_token_store.cc
  27. 18 13
      atom/browser/atom_browser_context.cc
  28. 12 5
      atom/browser/atom_browser_context.h
  29. 1 1
      atom/browser/atom_browser_main_parts.cc
  30. 5 5
      atom/browser/atom_browser_main_parts_posix.cc
  31. 8 1
      atom/browser/atom_resource_dispatcher_host_delegate.cc
  32. 4 0
      atom/browser/auto_updater.cc
  33. 1 0
      atom/browser/auto_updater.h
  34. 7 0
      atom/browser/auto_updater_mac.mm
  35. 6 0
      atom/browser/browser.cc
  36. 15 5
      atom/browser/browser.h
  37. 7 0
      atom/browser/browser_linux.cc
  38. 19 1
      atom/browser/browser_mac.mm
  39. 3 0
      atom/browser/browser_observer.h
  40. 33 0
      atom/browser/browser_win.cc
  41. 7 8
      atom/browser/common_web_contents_delegate.cc
  42. 5 0
      atom/browser/common_web_contents_delegate_mac.mm
  43. 2 0
      atom/browser/mac/atom_application.mm
  44. 1 3
      atom/browser/mac/atom_application_delegate.h
  45. 7 9
      atom/browser/mac/atom_application_delegate.mm
  46. 4 47
      atom/browser/native_window.cc
  47. 3 45
      atom/browser/native_window.h
  48. 0 1
      atom/browser/native_window_mac.h
  49. 26 22
      atom/browser/native_window_mac.mm
  50. 76 22
      atom/browser/native_window_views.cc
  51. 9 3
      atom/browser/native_window_views.h
  52. 5 3
      atom/browser/native_window_views_win.cc
  53. 1 1
      atom/browser/net/asar/asar_protocol_handler.cc
  54. 3 3
      atom/browser/net/asar/url_request_asar_job.cc
  55. 2 9
      atom/browser/net/atom_cert_verifier.cc
  56. 1 3
      atom/browser/net/atom_cert_verifier.h
  57. 8 4
      atom/browser/net/atom_url_request_job_factory.cc
  58. 3 0
      atom/browser/net/atom_url_request_job_factory.h
  59. 1 1
      atom/browser/net/url_request_async_asar_job.cc
  60. 1 1
      atom/browser/net/url_request_buffer_job.cc
  61. 1 1
      atom/browser/net/url_request_string_job.cc
  62. 10 0
      atom/browser/relauncher_linux.cc
  63. 10 2
      atom/browser/relauncher_mac.cc
  64. 2 2
      atom/browser/resources/mac/Info.plist
  65. 4 4
      atom/browser/resources/win/atom.rc
  66. 8 8
      atom/browser/ui/accelerator_util.cc
  67. 4 6
      atom/browser/ui/accelerator_util.h
  68. 16 0
      atom/browser/ui/atom_menu_model.cc
  69. 19 0
      atom/browser/ui/atom_menu_model.h
  70. 7 11
      atom/browser/ui/cocoa/atom_menu_controller.h
  71. 18 22
      atom/browser/ui/cocoa/atom_menu_controller.mm
  72. 5 4
      atom/browser/ui/file_dialog.h
  73. 12 10
      atom/browser/ui/file_dialog_gtk.cc
  74. 2 0
      atom/browser/ui/file_dialog_mac.mm
  75. 4 1
      atom/browser/ui/file_dialog_win.cc
  76. 3 3
      atom/browser/ui/message_box_gtk.cc
  77. 3 1
      atom/browser/ui/message_box_win.cc
  78. 5 1
      atom/browser/ui/tray_icon.cc
  79. 4 3
      atom/browser/ui/tray_icon.h
  80. 2 3
      atom/browser/ui/tray_icon_cocoa.h
  81. 17 7
      atom/browser/ui/tray_icon_cocoa.mm
  82. 1 1
      atom/browser/ui/tray_icon_gtk.cc
  83. 1 1
      atom/browser/ui/tray_icon_gtk.h
  84. 1 0
      atom/browser/ui/tray_icon_observer.h
  85. 14 14
      atom/browser/ui/views/global_menu_bar_x11.cc
  86. 3 3
      atom/browser/ui/views/global_menu_bar_x11.h
  87. 5 5
      atom/browser/ui/views/menu_bar.cc
  88. 4 7
      atom/browser/ui/views/menu_bar.h
  89. 5 5
      atom/browser/ui/views/menu_delegate.cc
  90. 2 5
      atom/browser/ui/views/menu_delegate.h
  91. 28 0
      atom/browser/ui/views/menu_model_adapter.cc
  92. 29 0
      atom/browser/ui/views/menu_model_adapter.h
  93. 2 2
      atom/browser/ui/win/notify_icon.cc
  94. 3 3
      atom/browser/ui/win/notify_icon.h
  95. 16 0
      atom/browser/ui/win/taskbar_host.cc
  96. 4 0
      atom/browser/ui/win/taskbar_host.h
  97. 27 0
      atom/browser/unresponsive_suppressor.cc
  98. 25 0
      atom/browser/unresponsive_suppressor.h
  99. 8 4
      atom/browser/web_view_guest_delegate.cc
  100. 2 3
      atom/browser/web_view_guest_delegate.h

+ 1 - 1
.node-version

@@ -1 +1 @@
-v6.1.0
+v6.3.0

+ 1 - 0
README-ko.md

@@ -75,6 +75,7 @@ npm install electron-prebuilt --save-dev
 - [`electron-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
 - [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
 - [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
+- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(터키)* 커뮤니티
 
 [awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
 커뮤니티가 운영중인 유용한 예시 애플리케이션과 도구, 리소스가 있으니 참고하기 바랍니다.

+ 1 - 0
README.md

@@ -73,6 +73,7 @@ forums
 - [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
 - [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
 - [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
+- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
 
 Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
 for a community maintained list of useful example apps, tools and resources.

+ 3 - 2
atom/app/node_main.cc

@@ -7,7 +7,6 @@
 #include "atom/app/uv_task_runner.h"
 #include "atom/browser/javascript_environment.h"
 #include "atom/browser/node_debugger.h"
-#include "atom/common/node_includes.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -15,6 +14,8 @@
 #include "gin/public/isolate_holder.h"
 #include "gin/v8_initializer.h"
 
+#include "atom/common/node_includes.h"
+
 namespace atom {
 
 int NodeMain(int argc, char *argv[]) {
@@ -69,7 +70,7 @@ int NodeMain(int argc, char *argv[]) {
     exit_code = node::EmitExit(env);
     node::RunAtExit(env);
 
-    env->Dispose();
+    node::FreeEnvironment(env);
   }
 
   v8::V8::Dispose();

+ 1 - 1
atom/app/uv_task_runner.cc

@@ -21,7 +21,7 @@ UvTaskRunner::~UvTaskRunner() {
 bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
                                    const base::Closure& task,
                                    base::TimeDelta delay) {
-  uv_timer_t* timer = new uv_timer_t;
+  auto* timer = new uv_timer_t;
   timer->data = this;
   uv_timer_init(loop_, timer);
   uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);

+ 41 - 1
atom/browser/api/atom_api_app.cc

@@ -32,6 +32,7 @@
 #include "base/strings/string_util.h"
 #include "brightray/browser/brightray_paths.h"
 #include "chrome/common/chrome_paths.h"
+#include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/client_certificate_delegate.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/render_frame_host.h"
@@ -71,6 +72,30 @@ struct Converter<Browser::UserTask> {
 };
 #endif
 
+template<>
+struct Converter<Browser::LoginItemSettings> {
+  static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
+                     Browser::LoginItemSettings* out) {
+    mate::Dictionary dict;
+    if (!ConvertFromV8(isolate, val, &dict))
+      return false;
+
+    dict.Get("openAtLogin", &(out->open_at_login));
+    dict.Get("openAsHidden", &(out->open_as_hidden));
+    return true;
+  }
+
+  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
+                                   Browser::LoginItemSettings val) {
+    mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
+    dict.Set("openAtLogin", val.open_at_login);
+    dict.Set("openAsHidden", val.open_as_hidden);
+    dict.Set("restoreState", val.restore_state);
+    dict.Set("wasOpenedAtLogin", val.opened_at_login);
+    dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
+    return dict.GetHandle();
+  }
+};
 }  // namespace mate
 
 
@@ -254,6 +279,10 @@ void App::OnFinishLaunching() {
   Emit("ready");
 }
 
+void App::OnAccessibilitySupportChanged() {
+  Emit("accessibility-support-changed", IsAccessibilitySupportEnabled());
+}
+
 #if defined(OS_MACOSX)
 void App::OnContinueUserActivity(
     bool* prevent_default,
@@ -459,11 +488,16 @@ void App::DisableHardwareAcceleration(mate::Arguments* args) {
   content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
 }
 
+bool App::IsAccessibilitySupportEnabled() {
+  auto ax_state = content::BrowserAccessibilityState::GetInstance();
+  return ax_state->IsAccessibleBrowser();
+}
+
 #if defined(USE_NSS_CERTS)
 void App::ImportCertificate(
     const base::DictionaryValue& options,
     const net::CompletionCallback& callback) {
-  auto browser_context = brightray::BrowserContext::From("", false);
+  auto browser_context = AtomBrowserContext::From("", false);
   if (!certificate_manager_model_) {
     std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
     CertificateManagerModel::Create(
@@ -522,6 +556,10 @@ void App::BuildPrototype(
                  base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
       .SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
       .SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
+      .SetMethod("getLoginItemSettings",
+                 base::Bind(&Browser::GetLoginItemSettings, browser))
+      .SetMethod("setLoginItemSettings",
+                 base::Bind(&Browser::SetLoginItemSettings, browser))
 #if defined(OS_MACOSX)
       .SetMethod("hide", base::Bind(&Browser::Hide, browser))
       .SetMethod("show", base::Bind(&Browser::Show, browser))
@@ -547,6 +585,8 @@ void App::BuildPrototype(
       .SetMethod("makeSingleInstance", &App::MakeSingleInstance)
       .SetMethod("releaseSingleInstance", &App::ReleaseSingleInstance)
       .SetMethod("relaunch", &App::Relaunch)
+      .SetMethod("isAccessibilitySupportEnabled",
+                 &App::IsAccessibilitySupportEnabled)
       .SetMethod("disableHardwareAcceleration",
                  &App::DisableHardwareAcceleration);
 }

+ 2 - 0
atom/browser/api/atom_api_app.h

@@ -72,6 +72,7 @@ class App : public AtomBrowserClient::Delegate,
   void OnFinishLaunching() override;
   void OnLogin(LoginHandler* login_handler,
                const base::DictionaryValue& request_details) override;
+  void OnAccessibilitySupportChanged() override;
 #if defined(OS_MACOSX)
   void OnContinueUserActivity(
       bool* prevent_default,
@@ -113,6 +114,7 @@ class App : public AtomBrowserClient::Delegate,
   void ReleaseSingleInstance();
   bool Relaunch(mate::Arguments* args);
   void DisableHardwareAcceleration(mate::Arguments* args);
+  bool IsAccessibilitySupportEnabled();
 #if defined(USE_NSS_CERTS)
   void ImportCertificate(const base::DictionaryValue& options,
                          const net::CompletionCallback& callback);

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

@@ -109,6 +109,7 @@ void AutoUpdater::BuildPrototype(
     v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
   mate::ObjectTemplateBuilder(isolate, prototype)
       .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
+      .SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
       .SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
       .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
 }

+ 1 - 0
atom/browser/api/atom_api_auto_updater.h

@@ -44,6 +44,7 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
   void OnWindowAllClosed() override;
 
  private:
+  std::string GetFeedURL();
   void SetFeedURL(const std::string& url, mate::Arguments* args);
   void QuitAndInstall();
 

+ 7 - 4
atom/browser/api/atom_api_menu.cc

@@ -21,7 +21,7 @@ namespace api {
 
 Menu::Menu(v8::Isolate* isolate)
     : model_(new AtomMenuModel(this)),
-      parent_(NULL) {
+      parent_(nullptr) {
 }
 
 Menu::~Menu() {
@@ -53,11 +53,14 @@ bool Menu::IsCommandIdVisible(int command_id) const {
   return is_visible_.Run(command_id);
 }
 
-bool Menu::GetAcceleratorForCommandId(int command_id,
-                                      ui::Accelerator* accelerator) {
+bool Menu::GetAcceleratorForCommandIdWithParams(
+    int command_id,
+    bool use_default_accelerator,
+    ui::Accelerator* accelerator) const {
   v8::Locker locker(isolate());
   v8::HandleScope handle_scope(isolate());
-  v8::Local<v8::Value> val = get_accelerator_.Run(command_id);
+  v8::Local<v8::Value> val = get_accelerator_.Run(
+      command_id, use_default_accelerator);
   return mate::ConvertFromV8(isolate(), val, accelerator);
 }
 

+ 5 - 3
atom/browser/api/atom_api_menu.h

@@ -46,8 +46,10 @@ class Menu : public mate::TrackableObject<Menu>,
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdVisible(int command_id) const override;
-  bool GetAcceleratorForCommandId(int command_id,
-                                  ui::Accelerator* accelerator) override;
+  bool GetAcceleratorForCommandIdWithParams(
+      int command_id,
+      bool use_default_accelerator,
+      ui::Accelerator* accelerator) const override;
   void ExecuteCommand(int command_id, int event_flags) override;
   void MenuWillShow(ui::SimpleMenuModel* source) override;
 
@@ -89,7 +91,7 @@ class Menu : public mate::TrackableObject<Menu>,
   base::Callback<bool(int)> is_checked_;
   base::Callback<bool(int)> is_enabled_;
   base::Callback<bool(int)> is_visible_;
-  base::Callback<v8::Local<v8::Value>(int)> get_accelerator_;
+  base::Callback<v8::Local<v8::Value>(int, bool)> get_accelerator_;
   base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
   base::Callback<void()> menu_will_show_;
 

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

@@ -5,6 +5,7 @@
 #import "atom/browser/api/atom_api_menu_mac.h"
 
 #include "atom/browser/native_window.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "brightray/browser/inspectable_web_contents.h"
@@ -30,7 +31,8 @@ void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
     return;
 
   base::scoped_nsobject<AtomMenuController> menu_controller(
-      [[AtomMenuController alloc] initWithModel:model_.get()]);
+      [[AtomMenuController alloc] initWithModel:model_.get()
+                          useDefaultAccelerator:NO]);
   NSMenu* menu = [menu_controller menu];
   NSView* view = web_contents->GetView()->GetNativeView();
 
@@ -66,6 +68,9 @@ void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
   if (rightmostMenuPoint > screenRight)
     position.x = position.x - [menu size].width;
 
+  // Don't emit unresponsive event when showing menu.
+  atom::UnresponsiveSuppressor suppressor;
+
   // Show the menu.
   [menu popUpMenuPositioningItem:item atLocation:position inView:view];
 }
@@ -74,7 +79,8 @@ void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
 void Menu::SetApplicationMenu(Menu* base_menu) {
   MenuMac* menu = static_cast<MenuMac*>(base_menu);
   base::scoped_nsobject<AtomMenuController> menu_controller(
-      [[AtomMenuController alloc] initWithModel:menu->model_.get()]);
+      [[AtomMenuController alloc] initWithModel:menu->model_.get()
+                          useDefaultAccelerator:YES]);
   [NSApp setMainMenu:[menu_controller menu]];
 
   // Ensure the menu_controller_ is destroyed after main menu is set.

+ 4 - 0
atom/browser/api/atom_api_menu_views.cc

@@ -5,6 +5,7 @@
 #include "atom/browser/api/atom_api_menu_views.h"
 
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "ui/display/screen.h"
 #include "ui/views/controls/menu/menu_runner.h"
@@ -36,6 +37,9 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
     location = gfx::Point(origin.x() + x, origin.y() + y);
   }
 
+  // Don't emit unresponsive event when showing menu.
+  atom::UnresponsiveSuppressor suppressor;
+
   // Show the menu.
   views::MenuRunner menu_runner(
       model(),

+ 26 - 1
atom/browser/api/atom_api_protocol.cc

@@ -6,6 +6,7 @@
 
 #include "atom/browser/atom_browser_client.h"
 #include "atom/browser/atom_browser_main_parts.h"
+#include "atom/browser/browser.h"
 #include "atom/browser/net/url_request_async_asar_job.h"
 #include "atom/browser/net/url_request_buffer_job.h"
 #include "atom/browser/net/url_request_fetch_job.h"
@@ -26,12 +27,30 @@ namespace atom {
 
 namespace api {
 
+namespace {
+
+// Clear protocol handlers in IO thread.
+void ClearJobFactoryInIO(
+    scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
+  auto job_factory = static_cast<AtomURLRequestJobFactory*>(
+      request_context_getter->job_factory());
+  job_factory->Clear();
+}
+
+}  // namespace
+
 Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
     : request_context_getter_(browser_context->GetRequestContext()),
       weak_factory_(this) {
   Init(isolate);
 }
 
+Protocol::~Protocol() {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(ClearJobFactoryInIO, request_context_getter_));
+}
+
 void Protocol::RegisterServiceWorkerSchemes(
     const std::vector<std::string>& schemes) {
   atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
@@ -173,7 +192,13 @@ void Protocol::BuildPrototype(
 namespace {
 
 void RegisterStandardSchemes(
-    const std::vector<std::string>& schemes) {
+    const std::vector<std::string>& schemes, mate::Arguments* args) {
+  if (atom::Browser::Get()->is_ready()) {
+    args->ThrowError("protocol.registerStandardSchemes should be called before "
+                     "app is ready");
+    return;
+  }
+
   auto policy = content::ChildProcessSecurityPolicy::GetInstance();
   for (const auto& scheme : schemes) {
     url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);

+ 1 - 0
atom/browser/api/atom_api_protocol.h

@@ -43,6 +43,7 @@ class Protocol : public mate::TrackableObject<Protocol> {
 
  protected:
   Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
+  ~Protocol();
 
  private:
   // Possible errors.

+ 56 - 17
atom/browser/api/atom_api_session.cc

@@ -11,6 +11,7 @@
 #include "atom/browser/api/atom_api_download_item.h"
 #include "atom/browser/api/atom_api_protocol.h"
 #include "atom/browser/api/atom_api_web_request.h"
+#include "atom/browser/browser.h"
 #include "atom/browser/atom_browser_context.h"
 #include "atom/browser/atom_browser_main_parts.h"
 #include "atom/browser/atom_permission_manager.h"
@@ -20,6 +21,7 @@
 #include "atom/common/native_mate_converters/gurl_converter.h"
 #include "atom/common/native_mate_converters/file_path_converter.h"
 #include "atom/common/native_mate_converters/net_converter.h"
+#include "atom/common/native_mate_converters/value_converter.h"
 #include "atom/common/node_includes.h"
 #include "base/files/file_path.h"
 #include "base/guid.h"
@@ -163,6 +165,8 @@ namespace api {
 
 namespace {
 
+const char kPersistPrefix[] = "persist:";
+
 // The wrapSession funtion which is implemented in JavaScript
 using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>;
 WrapSessionCallback g_wrap_session;
@@ -241,10 +245,10 @@ void OnGetBackend(disk_cache::Backend** backend_ptr,
     } else if (action == Session::CacheAction::STATS) {
       base::StringPairs stats;
       (*backend_ptr)->GetStats(&stats);
-      for (size_t i = 0; i < stats.size(); ++i) {
-        if (stats[i].first == "Current size") {
+      for (const auto& stat : stats) {
+        if (stat.first == "Current size") {
           int current_size;
-          base::StringToInt(stats[i].second, &current_size);
+          base::StringToInt(stat.second, &current_size);
           RunCallbackInUI(callback, current_size);
           break;
         }
@@ -266,7 +270,7 @@ void DoCacheActionInIO(
 
   // Call GetBackend and make the backend's ptr accessable in OnGetBackend.
   using BackendPtr = disk_cache::Backend*;
-  BackendPtr* backend_ptr = new BackendPtr(nullptr);
+  auto* backend_ptr = new BackendPtr(nullptr);
   net::CompletionCallback on_get_backend =
       base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
   int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
@@ -285,6 +289,14 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
   RunCallbackInUI(callback);
 }
 
+void SetCertVerifyProcInIO(
+    const scoped_refptr<net::URLRequestContextGetter>& context_getter,
+    const AtomCertVerifier::VerifyProc& proc) {
+  auto request_context = context_getter->GetURLRequestContext();
+  static_cast<AtomCertVerifier*>(request_context->cert_verifier())->
+      SetVerifyProc(proc);
+}
+
 void ClearHostResolverCacheInIO(
     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
     const base::Closure& callback) {
@@ -311,6 +323,11 @@ void AllowNTLMCredentialsForDomainsInIO(
   }
 }
 
+void OnClearStorageDataDone(const base::Closure& callback) {
+  if (!callback.is_null())
+    callback.Run();
+}
+
 }  // namespace
 
 Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
@@ -360,21 +377,19 @@ void Session::DoCacheAction(const net::CompletionCallback& callback) {
 }
 
 void Session::ClearStorageData(mate::Arguments* args) {
-  // clearStorageData([options, ]callback)
+  // clearStorageData([options, callback])
   ClearStorageDataOptions options;
-  args->GetNext(&options);
   base::Closure callback;
-  if (!args->GetNext(&callback)) {
-    args->ThrowError();
-    return;
-  }
+  args->GetNext(&options);
+  args->GetNext(&callback);
 
   auto storage_partition =
       content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
   storage_partition->ClearData(
       options.storage_types, options.quota_types, options.origin,
       content::StoragePartition::OriginMatcherFunction(),
-      base::Time(), base::Time::Max(), callback);
+      base::Time(), base::Time::Max(),
+      base::Bind(&OnClearStorageDataDone, callback));
 }
 
 void Session::FlushStorageData() {
@@ -434,7 +449,10 @@ void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
     return;
   }
 
-  browser_context_->cert_verifier()->SetVerifyProc(proc);
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+      base::Bind(&SetCertVerifyProcInIO,
+                 make_scoped_refptr(browser_context_->GetRequestContext()),
+                 proc));
 }
 
 void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
@@ -522,10 +540,19 @@ mate::Handle<Session> Session::CreateFrom(
 
 // static
 mate::Handle<Session> Session::FromPartition(
-    v8::Isolate* isolate, const std::string& partition, bool in_memory) {
-  auto browser_context = brightray::BrowserContext::From(partition, in_memory);
-  return CreateFrom(isolate,
-                    static_cast<AtomBrowserContext*>(browser_context.get()));
+    v8::Isolate* isolate, const std::string& partition,
+    const base::DictionaryValue& options) {
+  scoped_refptr<AtomBrowserContext> browser_context;
+  if (partition.empty()) {
+    browser_context = AtomBrowserContext::From("", false, options);
+  } else if (base::StartsWith(partition, kPersistPrefix,
+                              base::CompareCase::SENSITIVE)) {
+    std::string name = partition.substr(8);
+    browser_context = AtomBrowserContext::From(name, false, options);
+  } else {
+    browser_context = AtomBrowserContext::From(partition, true, options);
+  }
+  return CreateFrom(isolate, browser_context.get());
 }
 
 // static
@@ -565,11 +592,23 @@ void SetWrapSession(const WrapSessionCallback& callback) {
 
 namespace {
 
+v8::Local<v8::Value> FromPartition(
+    const std::string& partition, mate::Arguments* args) {
+  if (!atom::Browser::Get()->is_ready()) {
+    args->ThrowError("Session can only be received when app is ready");
+    return v8::Null(args->isolate());
+  }
+  base::DictionaryValue options;
+  args->GetNext(&options);
+  return atom::api::Session::FromPartition(
+      args->isolate(), partition, options).ToV8();
+}
+
 void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
                 v8::Local<v8::Context> context, void* priv) {
   v8::Isolate* isolate = context->GetIsolate();
   mate::Dictionary dict(isolate, exports);
-  dict.SetMethod("fromPartition", &atom::api::Session::FromPartition);
+  dict.SetMethod("fromPartition", &FromPartition);
   dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
 }
 

+ 4 - 2
atom/browser/api/atom_api_session.h

@@ -8,6 +8,7 @@
 #include <string>
 
 #include "atom/browser/api/trackable_object.h"
+#include "base/values.h"
 #include "content/public/browser/download_manager.h"
 #include "native_mate/handle.h"
 #include "net/base/completion_callback.h"
@@ -47,9 +48,10 @@ class Session: public mate::TrackableObject<Session>,
   static mate::Handle<Session> CreateFrom(
       v8::Isolate* isolate, AtomBrowserContext* browser_context);
 
-  // Gets the Session of |partition| and |in_memory|.
+  // Gets the Session of |partition|.
   static mate::Handle<Session> FromPartition(
-      v8::Isolate* isolate, const std::string& partition, bool in_memory);
+      v8::Isolate* isolate, const std::string& partition,
+      const base::DictionaryValue& options = base::DictionaryValue());
 
   AtomBrowserContext* browser_context() const { return browser_context_.get(); }
 

+ 6 - 0
atom/browser/api/atom_api_tray.cc

@@ -29,6 +29,8 @@ Tray::Tray(v8::Isolate* isolate, mate::Handle<NativeImage> image)
 }
 
 Tray::~Tray() {
+  // Destroy the native tray in next tick.
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, tray_icon_.release());
 }
 
 // static
@@ -74,6 +76,10 @@ void Tray::OnDropFiles(const std::vector<std::string>& files) {
   Emit("drop-files", files);
 }
 
+void Tray::OnDropText(const std::string& text) {
+  Emit("drop-text", text);
+}
+
 void Tray::OnDragEntered() {
   Emit("drag-enter");
 }

+ 1 - 0
atom/browser/api/atom_api_tray.h

@@ -53,6 +53,7 @@ class Tray : public mate::TrackableObject<Tray>,
   void OnBalloonClosed() override;
   void OnDrop() override;
   void OnDropFiles(const std::vector<std::string>& files) override;
+  void OnDropText(const std::string& text) override;
   void OnDragEntered() override;
   void OnDragExited() override;
   void OnDragEnded() override;

+ 84 - 32
atom/browser/api/atom_api_web_contents.cc

@@ -47,6 +47,7 @@
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -65,6 +66,7 @@
 #include "net/url_request/url_request_context.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/web/WebFindOptions.h"
+#include "ui/gfx/screen.h"
 
 #include "atom/common/node_includes.h"
 
@@ -238,6 +240,13 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
   return storage_partition->GetServiceWorkerContext();
 }
 
+// Called when CapturePage is done.
+void OnCapturePageDone(base::Callback<void(const gfx::Image&)> callback,
+                       const SkBitmap& bitmap,
+                       content::ReadbackResponse response) {
+  callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap));
+}
+
 }  // namespace
 
 WebContents::WebContents(v8::Isolate* isolate,
@@ -277,16 +286,11 @@ WebContents::WebContents(v8::Isolate* isolate,
   std::string partition;
   mate::Handle<api::Session> session;
   if (options.Get("session", &session)) {
-  } else if (options.Get("partition", &partition) && !partition.empty()) {
-    bool in_memory = true;
-    if (base::StartsWith(partition, "persist:", base::CompareCase::SENSITIVE)) {
-      in_memory = false;
-      partition = partition.substr(8);
-    }
-    session = Session::FromPartition(isolate, partition, in_memory);
+  } else if (options.Get("partition", &partition)) {
+    session = Session::FromPartition(isolate, partition);
   } else {
     // Use the default session if not specified.
-    session = Session::FromPartition(isolate, "", false);
+    session = Session::FromPartition(isolate, "");
   }
   session_.Reset(isolate, session.ToV8());
 
@@ -600,20 +604,6 @@ void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
     Emit("did-finish-load");
 }
 
-void WebContents::DidFailProvisionalLoad(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& url,
-    int code,
-    const base::string16& description,
-    bool was_ignored_by_handler) {
-  bool is_main_frame = !render_frame_host->GetParent();
-  Emit("did-fail-provisional-load", code, description, url, is_main_frame);
-
-  // Do not emit "did-fail-load" for canceled requests.
-  if (code != net::ERR_ABORTED)
-    Emit("did-fail-load", code, description, url, is_main_frame);
-}
-
 void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
                               const GURL& url,
                               int error_code,
@@ -657,13 +647,27 @@ void WebContents::DidGetRedirectForResourceRequest(
        details.headers.get());
 }
 
-void WebContents::DidNavigateMainFrame(
-    const content::LoadCommittedDetails& details,
-    const content::FrameNavigateParams& params) {
-  if (details.is_navigation_to_different_page())
-    Emit("did-navigate", params.url);
-  else if (details.is_in_page)
-    Emit("did-navigate-in-page", params.url);
+void WebContents::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  bool is_main_frame = navigation_handle->IsInMainFrame();
+  if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) {
+    auto url = navigation_handle->GetURL();
+    bool is_in_page = navigation_handle->IsSamePage();
+    if (is_main_frame && !is_in_page) {
+      Emit("did-navigate", url);
+    } else if (is_in_page) {
+      Emit("did-navigate-in-page", url);
+    }
+  } else {
+    auto url = navigation_handle->GetURL();
+    int code = navigation_handle->GetNetErrorCode();
+    auto description = net::ErrorToShortString(code);
+    Emit("did-fail-provisional-load", code, description, url, is_main_frame);
+
+    // Do not emit "did-fail-load" for canceled requests.
+    if (code != net::ERR_ABORTED)
+      Emit("did-fail-load", code, description, url, is_main_frame);
+  }
 }
 
 void WebContents::TitleWasSet(content::NavigationEntry* entry,
@@ -677,10 +681,10 @@ void WebContents::TitleWasSet(content::NavigationEntry* entry,
 void WebContents::DidUpdateFaviconURL(
     const std::vector<content::FaviconURL>& urls) {
   std::set<GURL> unique_urls;
-  for (auto iter = urls.begin(); iter != urls.end(); ++iter) {
-    if (iter->icon_type != content::FaviconURL::FAVICON)
+  for (const auto& iter : urls) {
+    if (iter.icon_type != content::FaviconURL::FAVICON)
       continue;
-    const GURL& url = iter->icon_url;
+    const GURL& url = iter.icon_url;
     if (url.is_valid())
       unique_urls.insert(url);
   }
@@ -781,6 +785,13 @@ WebContents::Type WebContents::GetType() const {
   return type_;
 }
 
+#if !defined(OS_MACOSX)
+bool WebContents::IsFocused() const {
+  auto view = web_contents()->GetRenderWidgetHostView();
+  return view && view->HasFocus();
+}
+#endif
+
 bool WebContents::Equal(const WebContents* web_contents) const {
   return GetID() == web_contents->GetID();
 }
@@ -1235,6 +1246,45 @@ void WebContents::StartDrag(const mate::Dictionary& item,
   }
 }
 
+void WebContents::CapturePage(mate::Arguments* args) {
+  gfx::Rect rect;
+  base::Callback<void(const gfx::Image&)> callback;
+
+  if (!(args->Length() == 1 && args->GetNext(&callback)) &&
+      !(args->Length() == 2 && args->GetNext(&rect)
+                            && args->GetNext(&callback))) {
+    args->ThrowError();
+    return;
+  }
+
+  const auto view = web_contents()->GetRenderWidgetHostView();
+  const auto host = view ? view->GetRenderWidgetHost() : nullptr;
+  if (!view || !host) {
+    callback.Run(gfx::Image());
+    return;
+  }
+
+  // Capture full page if user doesn't specify a |rect|.
+  const gfx::Size view_size = rect.IsEmpty() ? view->GetViewBounds().size() :
+                                               rect.size();
+
+  // By default, the requested bitmap size is the view size in screen
+  // coordinates.  However, if there's more pixel detail available on the
+  // current system, increase the requested bitmap size to capture it all.
+  gfx::Size bitmap_size = view_size;
+  const gfx::NativeView native_view = view->GetNativeView();
+  const float scale =
+      gfx::Screen::GetScreen()->GetDisplayNearestWindow(native_view)
+      .device_scale_factor();
+  if (scale > 1.0f)
+    bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
+
+  host->CopyFromBackingStore(gfx::Rect(rect.origin(), view_size),
+                             bitmap_size,
+                             base::Bind(&OnCapturePageDone, callback),
+                             kBGRA_8888_SkColorType);
+}
+
 void WebContents::OnCursorChange(const content::WebCursor& cursor) {
   content::WebCursor::CursorInfo info;
   cursor.GetCursorInfo(&info);
@@ -1370,6 +1420,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
       .SetMethod("showDefinitionForSelection",
                  &WebContents::ShowDefinitionForSelection)
+      .SetMethod("capturePage", &WebContents::CapturePage)
+      .SetMethod("isFocused", &WebContents::IsFocused)
       .SetProperty("id", &WebContents::ID)
       .SetProperty("session", &WebContents::Session)
       .SetProperty("hostWebContents", &WebContents::HostWebContents)

+ 7 - 8
atom/browser/api/atom_api_web_contents.h

@@ -67,6 +67,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
 
   int GetID() const;
   Type GetType() const;
+  bool IsFocused() const;
   bool Equal(const WebContents* web_contents) const;
   void LoadURL(const GURL& url, const mate::Dictionary& options);
   void DownloadURL(const GURL& url);
@@ -145,6 +146,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
   // Dragging native items.
   void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
 
+  // Captures the page with |rect|, |callback| would be called when capturing is
+  // done.
+  void CapturePage(mate::Arguments* args);
+
   // Methods for creating <webview>.
   void SetSize(const SetSizeParams& params);
   bool IsGuest() const;
@@ -240,11 +245,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
                    int error_code,
                    const base::string16& error_description,
                    bool was_ignored_by_handler) override;
-  void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host,
-                              const GURL& validated_url,
-                              int error_code,
-                              const base::string16& error_description,
-                              bool was_ignored_by_handler) override;
   void DidStartLoading() override;
   void DidStopLoading() override;
   void DidGetResourceResponseStart(
@@ -252,9 +252,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
   void DidGetRedirectForResourceRequest(
       content::RenderFrameHost* render_frame_host,
       const content::ResourceRedirectDetails& details) override;
-  void DidNavigateMainFrame(
-      const content::LoadCommittedDetails& details,
-      const content::FrameNavigateParams& params) override;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
   bool OnMessageReceived(const IPC::Message& message) override;
   void WebContentsDestroyed() override;
   void NavigationEntryCommitted(

+ 30 - 0
atom/browser/api/atom_api_web_contents_mac.mm

@@ -0,0 +1,30 @@
+// Copyright (c) 2016 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_web_contents.h"
+
+@interface NSWindow
+- (BOOL)isKeyWindow;
+@end
+
+namespace atom {
+
+namespace api {
+
+bool WebContents::IsFocused() const {
+  if (GetType() != BACKGROUND_PAGE) {
+    auto window = web_contents()->GetTopLevelNativeWindow();
+    // On Mac the render widget host view does not lose focus when the window
+    // loses focus so check if the top level window is the key window.
+    if (window && ![window isKeyWindow])
+      return false;
+  }
+
+  auto view = web_contents()->GetRenderWidgetHostView();
+  return view && view->HasFocus();
+}
+
+}  // namespace api
+
+}  // namespace atom

+ 7 - 25
atom/browser/api/atom_api_window.cc

@@ -55,15 +55,6 @@ namespace api {
 
 namespace {
 
-void OnCapturePageDone(
-    v8::Isolate* isolate,
-    const base::Callback<void(const gfx::Image&)>& callback,
-    const SkBitmap& bitmap) {
-  v8::Locker locker(isolate);
-  v8::HandleScope handle_scope(isolate);
-  callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap));
-}
-
 // 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);
@@ -581,21 +572,6 @@ void Window::SetFocusable(bool focusable) {
   return window_->SetFocusable(focusable);
 }
 
-void Window::CapturePage(mate::Arguments* args) {
-  gfx::Rect rect;
-  base::Callback<void(const gfx::Image&)> callback;
-
-  if (!(args->Length() == 1 && args->GetNext(&callback)) &&
-      !(args->Length() == 2 && args->GetNext(&rect)
-                            && args->GetNext(&callback))) {
-    args->ThrowError();
-    return;
-  }
-
-  window_->CapturePage(
-      rect, base::Bind(&OnCapturePageDone, args->isolate(), callback));
-}
-
 void Window::SetProgressBar(double progress) {
   window_->SetProgressBar(progress);
 }
@@ -673,6 +649,12 @@ bool Window::IsWindowMessageHooked(UINT message) {
 void Window::UnhookAllWindowMessages() {
   messages_callback_map_.clear();
 }
+
+bool Window::SetThumbnailClip(const gfx::Rect& region) {
+  auto window = static_cast<NativeWindowViews*>(window_.get());
+  return window->taskbar_host().SetThumbnailClip(
+      window_->GetAcceleratedWidget(), region);
+}
 #endif
 
 #if defined(TOOLKIT_VIEWS)
@@ -843,7 +825,6 @@ void Window::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("focusOnWebView", &Window::FocusOnWebView)
       .SetMethod("blurWebView", &Window::BlurWebView)
       .SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
-      .SetMethod("capturePage", &Window::CapturePage)
       .SetMethod("setProgressBar", &Window::SetProgressBar)
       .SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
       .SetMethod("setThumbarButtons", &Window::SetThumbarButtons)
@@ -861,6 +842,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked)
       .SetMethod("unhookWindowMessage", &Window::UnhookWindowMessage)
       .SetMethod("unhookAllWindowMessages", &Window::UnhookAllWindowMessages)
+      .SetMethod("setThumbnailClip", &Window::SetThumbnailClip)
 #endif
 #if defined(TOOLKIT_VIEWS)
       .SetMethod("setIcon", &Window::SetIcon)

+ 1 - 1
atom/browser/api/atom_api_window.h

@@ -155,7 +155,6 @@ class Window : public mate::TrackableObject<Window>,
   void SetIgnoreMouseEvents(bool ignore);
   void SetContentProtection(bool enable);
   void SetFocusable(bool focusable);
-  void CapturePage(mate::Arguments* args);
   void SetProgressBar(double progress);
   void SetOverlayIcon(const gfx::Image& overlay,
                       const std::string& description);
@@ -180,6 +179,7 @@ class Window : public mate::TrackableObject<Window>,
   bool IsWindowMessageHooked(UINT message);
   void UnhookWindowMessage(UINT message);
   void UnhookAllWindowMessages();
+  bool SetThumbnailClip(const gfx::Rect& region);
 #endif
 
 #if defined(TOOLKIT_VIEWS)

+ 7 - 7
atom/browser/api/event.cc

@@ -12,8 +12,8 @@
 namespace mate {
 
 Event::Event(v8::Isolate* isolate)
-    : sender_(NULL),
-      message_(NULL) {
+    : sender_(nullptr),
+      message_(nullptr) {
   Init(isolate);
 }
 
@@ -31,8 +31,8 @@ void Event::SetSenderAndMessage(content::WebContents* sender,
 }
 
 void Event::WebContentsDestroyed() {
-  sender_ = NULL;
-  message_ = NULL;
+  sender_ = nullptr;
+  message_ = nullptr;
 }
 
 void Event::PreventDefault(v8::Isolate* isolate) {
@@ -41,13 +41,13 @@ void Event::PreventDefault(v8::Isolate* isolate) {
 }
 
 bool Event::SendReply(const base::string16& json) {
-  if (message_ == NULL || sender_ == NULL)
+  if (message_ == nullptr || sender_ == nullptr)
     return false;
 
   AtomViewHostMsg_Message_Sync::WriteReplyParams(message_, json);
   bool success = sender_->Send(message_);
-  message_ = NULL;
-  sender_ = NULL;
+  message_ = nullptr;
+  sender_ = nullptr;
   return success;
 }
 

+ 2 - 3
atom/browser/atom_access_token_store.cc

@@ -25,7 +25,6 @@ const char* kGeolocationProviderURL =
 }  // namespace
 
 AtomAccessTokenStore::AtomAccessTokenStore() {
-  LOG(ERROR) << "AtomAccessTokenStore";
   content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
 }
 
@@ -47,8 +46,8 @@ void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,
 }
 
 void AtomAccessTokenStore::GetRequestContextOnUIThread() {
-  auto browser_context = brightray::BrowserContext::From("", false);
-  request_context_getter_ = browser_context->url_request_context_getter();
+  auto browser_context = AtomBrowserContext::From("", false);
+  request_context_getter_ = browser_context->GetRequestContext();
 }
 
 void AtomAccessTokenStore::RespondOnOriginatingThread(

+ 18 - 13
atom/browser/atom_browser_context.cc

@@ -63,10 +63,10 @@ std::string RemoveWhitespace(const std::string& str) {
 
 }  // namespace
 
-AtomBrowserContext::AtomBrowserContext(const std::string& partition,
-                                       bool in_memory)
+AtomBrowserContext::AtomBrowserContext(
+    const std::string& partition, bool in_memory,
+    const base::DictionaryValue& options)
     : brightray::BrowserContext(partition, in_memory),
-      cert_verifier_(new AtomCertVerifier),
       network_delegate_(new AtomNetworkDelegate) {
   // Construct user agent string.
   Browser* browser = Browser::Get();
@@ -83,6 +83,10 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition,
         CHROME_VERSION_STRING);
   }
   user_agent_ = content::BuildUserAgentFromProduct(user_agent);
+
+  // Read options.
+  use_cache_ = true;
+  options.GetBoolean("cache", &use_cache_);
 }
 
 AtomBrowserContext::~AtomBrowserContext() {
@@ -145,7 +149,7 @@ net::HttpCache::BackendFactory*
 AtomBrowserContext::CreateHttpCacheBackendFactory(
     const base::FilePath& base_path) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kDisableHttpCache))
+  if (!use_cache_ || command_line->HasSwitch(switches::kDisableHttpCache))
     return new NoCacheBackend;
   else
     return brightray::BrowserContext::CreateHttpCacheBackendFactory(base_path);
@@ -174,7 +178,7 @@ content::PermissionManager* AtomBrowserContext::GetPermissionManager() {
 }
 
 std::unique_ptr<net::CertVerifier> AtomBrowserContext::CreateCertVerifier() {
-  return base::WrapUnique(cert_verifier_);
+  return base::WrapUnique(new AtomCertVerifier);
 }
 
 net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
@@ -191,14 +195,15 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
   pref_registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths);
 }
 
-}  // namespace atom
-
-namespace brightray {
-
 // static
-scoped_refptr<BrowserContext> BrowserContext::Create(
-    const std::string& partition, bool in_memory) {
-  return make_scoped_refptr(new atom::AtomBrowserContext(partition, in_memory));
+scoped_refptr<AtomBrowserContext> AtomBrowserContext::From(
+    const std::string& partition, bool in_memory,
+    const base::DictionaryValue& options) {
+  auto browser_context = brightray::BrowserContext::Get(partition, in_memory);
+  if (browser_context)
+    return static_cast<AtomBrowserContext*>(browser_context.get());
+
+  return new AtomBrowserContext(partition, in_memory, options);
 }
 
-}  // namespace brightray
+}  // namespace atom

+ 12 - 5
atom/browser/atom_browser_context.h

@@ -12,15 +12,18 @@
 namespace atom {
 
 class AtomDownloadManagerDelegate;
-class AtomCertVerifier;
 class AtomNetworkDelegate;
 class AtomPermissionManager;
 class WebViewManager;
 
 class AtomBrowserContext : public brightray::BrowserContext {
  public:
-  AtomBrowserContext(const std::string& partition, bool in_memory);
-  ~AtomBrowserContext() override;
+  // Get or create the BrowserContext according to its |partition| and
+  // |in_memory|. The |options| will be passed to constructor when there is no
+  // existing BrowserContext.
+  static scoped_refptr<AtomBrowserContext> From(
+      const std::string& partition, bool in_memory,
+      const base::DictionaryValue& options = base::DictionaryValue());
 
   void SetUserAgent(const std::string& user_agent);
 
@@ -42,17 +45,21 @@ class AtomBrowserContext : public brightray::BrowserContext {
   // brightray::BrowserContext:
   void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
 
-  AtomCertVerifier* cert_verifier() const { return cert_verifier_; }
   AtomNetworkDelegate* network_delegate() const { return network_delegate_; }
 
+ protected:
+  AtomBrowserContext(const std::string& partition, bool in_memory,
+                     const base::DictionaryValue& options);
+  ~AtomBrowserContext() override;
+
  private:
   std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
   std::unique_ptr<WebViewManager> guest_manager_;
   std::unique_ptr<AtomPermissionManager> permission_manager_;
   std::string user_agent_;
+  bool use_cache_;
 
   // Managed by brightray::BrowserContext.
-  AtomCertVerifier* cert_verifier_;
   AtomNetworkDelegate* network_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);

+ 1 - 1
atom/browser/atom_browser_main_parts.cc

@@ -32,7 +32,7 @@ void Erase(T* container, typename T::iterator iter) {
 }
 
 // static
-AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
+AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr;
 
 AtomBrowserMainParts::AtomBrowserMainParts()
     : fake_browser_process_(new BrowserProcess),

+ 5 - 5
atom/browser/atom_browser_main_parts_posix.cc

@@ -43,7 +43,7 @@ void GracefulShutdownHandler(int signal) {
   struct sigaction action;
   memset(&action, 0, sizeof(action));
   action.sa_handler = SIG_DFL;
-  RAW_CHECK(sigaction(signal, &action, NULL) == 0);
+  RAW_CHECK(sigaction(signal, &action, nullptr) == 0);
 
   RAW_CHECK(g_pipe_pid == getpid());
   RAW_CHECK(g_shutdown_pipe_write_fd != -1);
@@ -171,7 +171,7 @@ void AtomBrowserMainParts::HandleSIGCHLD() {
   struct sigaction action;
   memset(&action, 0, sizeof(action));
   action.sa_handler = SIGCHLDHandler;
-  CHECK_EQ(sigaction(SIGCHLD, &action, NULL), 0);
+  CHECK_EQ(sigaction(SIGCHLD, &action, nullptr), 0);
 }
 
 void AtomBrowserMainParts::HandleShutdownSignals() {
@@ -211,15 +211,15 @@ void AtomBrowserMainParts::HandleShutdownSignals() {
   struct sigaction action;
   memset(&action, 0, sizeof(action));
   action.sa_handler = SIGTERMHandler;
-  CHECK_EQ(sigaction(SIGTERM, &action, NULL), 0);
+  CHECK_EQ(sigaction(SIGTERM, &action, nullptr), 0);
   // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
   // the browser process is being debugged, GDB will catch the SIGINT first.
   action.sa_handler = SIGINTHandler;
-  CHECK_EQ(sigaction(SIGINT, &action, NULL), 0);
+  CHECK_EQ(sigaction(SIGINT, &action, nullptr), 0);
   // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
   // distros send SIGHUP, SIGTERM, and then SIGKILL.
   action.sa_handler = SIGHUPHandler;
-  CHECK_EQ(sigaction(SIGHUP, &action, NULL), 0);
+  CHECK_EQ(sigaction(SIGHUP, &action, nullptr), 0);
 }
 
 }  // namespace atom

+ 8 - 1
atom/browser/atom_resource_dispatcher_host_delegate.cc

@@ -7,6 +7,7 @@
 #include "atom/browser/login_handler.h"
 #include "atom/browser/web_contents_permission_helper.h"
 #include "atom/common/platform_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/escape.h"
 #include "url/gurl.h"
@@ -20,7 +21,13 @@ namespace {
 void OnOpenExternal(const GURL& escaped_url,
                     bool allowed) {
   if (allowed)
-    platform_util::OpenExternal(escaped_url, true);
+    platform_util::OpenExternal(
+#if defined(OS_WIN)
+        base::UTF8ToUTF16(escaped_url.spec()),
+#else
+        escaped_url,
+#endif
+        true);
 }
 
 void HandleExternalProtocolInUI(

+ 4 - 0
atom/browser/auto_updater.cc

@@ -17,6 +17,10 @@ void AutoUpdater::SetDelegate(Delegate* delegate) {
 }
 
 #if !defined(OS_MACOSX) || defined(MAS_BUILD)
+std::string AutoUpdater::GetFeedURL() {
+  return "";
+}
+
 void AutoUpdater::SetFeedURL(const std::string& url,
                              const HeaderMap& requestHeaders) {
 }

+ 1 - 0
atom/browser/auto_updater.h

@@ -49,6 +49,7 @@ class AutoUpdater {
   static Delegate* GetDelegate();
   static void SetDelegate(Delegate* delegate);
 
+  static std::string GetFeedURL();
   static void SetFeedURL(const std::string& url,
                          const HeaderMap& requestHeaders);
   static void CheckForUpdates();

+ 7 - 0
atom/browser/auto_updater_mac.mm

@@ -25,9 +25,14 @@ SQRLUpdater* g_updater = nil;
 namespace {
 
 bool g_update_available = false;
+std::string update_url_ = "";
 
 }
 
+std::string AutoUpdater::GetFeedURL() {
+  return update_url_;
+}
+
 // static
 void AutoUpdater::SetFeedURL(const std::string& feed,
                              const HeaderMap& requestHeaders) {
@@ -35,6 +40,8 @@ void AutoUpdater::SetFeedURL(const std::string& feed,
   if (!delegate)
     return;
 
+  update_url_ = feed;
+
   NSURL* url = [NSURL URLWithString:base::SysUTF8ToNSString(feed)];
   NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
 

+ 6 - 0
atom/browser/browser.cc

@@ -155,6 +155,12 @@ void Browser::DidFinishLaunching() {
   FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching());
 }
 
+void Browser::OnAccessibilitySupportChanged() {
+  FOR_EACH_OBSERVER(BrowserObserver,
+                    observers_,
+                    OnAccessibilitySupportChanged());
+}
+
 void Browser::RequestLogin(
     LoginHandler* login_handler,
     std::unique_ptr<base::DictionaryValue> request_details) {

+ 15 - 5
atom/browser/browser.h

@@ -25,16 +25,13 @@ class DictionaryValue;
 class FilePath;
 }
 
-namespace ui {
-class MenuModel;
-}
-
 namespace gfx {
 class Image;
 }
 
 namespace atom {
 
+class AtomMenuModel;
 class LoginHandler;
 
 // This class is used for control application-wide operations.
@@ -91,6 +88,17 @@ class Browser : public WindowListObserver {
   bool SetBadgeCount(int count);
   int GetBadgeCount();
 
+  // Set/Get the login item settings of the app
+  struct LoginItemSettings {
+    bool open_at_login = false;
+    bool open_as_hidden = false;
+    bool restore_state = false;
+    bool opened_at_login = false;
+    bool opened_as_hidden = false;
+  };
+  void SetLoginItemSettings(LoginItemSettings settings);
+  LoginItemSettings GetLoginItemSettings();
+
 #if defined(OS_MACOSX)
   // Hide the application.
   void Hide();
@@ -130,7 +138,7 @@ class Browser : public WindowListObserver {
   void DockShow();
 
   // Set docks' menu.
-  void DockSetMenu(ui::MenuModel* model);
+  void DockSetMenu(AtomMenuModel* model);
 
   // Set docks' icon.
   void DockSetIcon(const gfx::Image& image);
@@ -174,6 +182,8 @@ class Browser : public WindowListObserver {
   void WillFinishLaunching();
   void DidFinishLaunching();
 
+  void OnAccessibilitySupportChanged();
+
   // Request basic auth login.
   void RequestLogin(LoginHandler* login_handler,
                     std::unique_ptr<base::DictionaryValue> request_details);

+ 7 - 0
atom/browser/browser_linux.cc

@@ -57,6 +57,13 @@ bool Browser::SetBadgeCount(int count) {
   }
 }
 
+void Browser::SetLoginItemSettings(LoginItemSettings settings) {
+}
+
+Browser::LoginItemSettings Browser::GetLoginItemSettings() {
+  return LoginItemSettings();
+}
+
 std::string Browser::GetExecutableFileVersion() const {
   return brightray::GetApplicationVersion();
 }

+ 19 - 1
atom/browser/browser_mac.mm

@@ -11,6 +11,7 @@
 #include "atom/browser/window_list.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/foundation_util.h"
+#include "base/mac/mac_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/sys_string_conversions.h"
 #include "brightray/common/application_info.h"
@@ -148,6 +149,23 @@ bool Browser::ContinueUserActivity(const std::string& type,
   return prevent_default;
 }
 
+Browser::LoginItemSettings Browser::GetLoginItemSettings() {
+  LoginItemSettings settings;
+  settings.open_at_login = base::mac::CheckLoginItemStatus(
+      &settings.open_as_hidden);
+  settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState();
+  settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem();
+  settings.opened_as_hidden = base::mac::WasLaunchedAsHiddenLoginItem();
+  return settings;
+}
+
+void Browser::SetLoginItemSettings(LoginItemSettings settings) {
+  if (settings.open_at_login)
+    base::mac::AddToLoginItems(settings.open_as_hidden);
+  else
+    base::mac::RemoveFromLoginItems();
+}
+
 std::string Browser::GetExecutableFileVersion() const {
   return brightray::GetApplicationVersion();
 }
@@ -216,7 +234,7 @@ void Browser::DockShow() {
   }
 }
 
-void Browser::DockSetMenu(ui::MenuModel* model) {
+void Browser::DockSetMenu(AtomMenuModel* model) {
   AtomApplicationDelegate* delegate = (AtomApplicationDelegate*)[NSApp delegate];
   [delegate setApplicationDockMenu:model];
 }

+ 3 - 0
atom/browser/browser_observer.h

@@ -52,6 +52,9 @@ class BrowserObserver {
   virtual void OnLogin(LoginHandler* login_handler,
                        const base::DictionaryValue& request_details) {}
 
+  // The browser's accessibility suppport has changed.
+  virtual void OnAccessibilitySupportChanged() {}
+
 #if defined(OS_MACOSX)
   // The browser wants to resume a user activity via handoff. (macOS only)
   virtual void OnContinueUserActivity(

+ 33 - 0
atom/browser/browser_win.cc

@@ -272,6 +272,39 @@ bool Browser::SetBadgeCount(int count) {
   return false;
 }
 
+void Browser::SetLoginItemSettings(LoginItemSettings settings) {
+  std::wstring keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
+  base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
+
+  if (settings.open_at_login) {
+    base::FilePath path;
+    if (PathService::Get(base::FILE_EXE, &path)) {
+      std::wstring exePath(path.value());
+      key.WriteValue(GetAppUserModelID(), exePath.c_str());
+    }
+  } else {
+    key.DeleteValue(GetAppUserModelID());
+  }
+}
+
+Browser::LoginItemSettings Browser::GetLoginItemSettings() {
+  LoginItemSettings settings;
+  std::wstring keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
+  base::win::RegKey key(HKEY_CURRENT_USER, keyPath.c_str(), KEY_ALL_ACCESS);
+  std::wstring keyVal;
+
+  if (!FAILED(key.ReadValue(GetAppUserModelID(), &keyVal))) {
+    base::FilePath path;
+    if (PathService::Get(base::FILE_EXE, &path)) {
+      std::wstring exePath(path.value());
+      settings.open_at_login = keyVal == exePath;
+    }
+  }
+
+  return settings;
+}
+
+
 PCWSTR Browser::GetAppUserModelID() {
   if (app_user_model_id_.empty()) {
     SetAppUserModelID(base::ReplaceStringPlaceholders(

+ 7 - 8
atom/browser/common_web_contents_delegate.cc

@@ -94,7 +94,7 @@ FileSystem CreateFileSystemStruct(
 }
 
 base::DictionaryValue* CreateFileSystemValue(const FileSystem& file_system) {
-  base::DictionaryValue* file_system_value = new base::DictionaryValue();
+  auto* file_system_value = new base::DictionaryValue();
   file_system_value->SetString("fileSystemName", file_system.file_system_name);
   file_system_value->SetString("rootURL", file_system.root_url);
   file_system_value->SetString("fileSystemPath", file_system.file_system_path);
@@ -377,7 +377,7 @@ content::SecurityStyle CommonWebContentsDelegate::GetSecurityStyle(
 void CommonWebContentsDelegate::DevToolsSaveToFile(
     const std::string& url, const std::string& content, bool save_as) {
   base::FilePath path;
-  PathsMap::iterator it = saved_files_.find(url);
+  auto it = saved_files_.find(url);
   if (it != saved_files_.end() && !save_as) {
     path = it->second;
   } else {
@@ -402,7 +402,7 @@ void CommonWebContentsDelegate::DevToolsSaveToFile(
 
 void CommonWebContentsDelegate::DevToolsAppendToFile(
     const std::string& url, const std::string& content) {
-  PathsMap::iterator it = saved_files_.find(url);
+  auto it = saved_files_.find(url);
   if (it == saved_files_.end())
     return;
 
@@ -435,8 +435,8 @@ void CommonWebContentsDelegate::DevToolsRequestFileSystems() {
   }
 
   base::ListValue file_system_value;
-  for (size_t i = 0; i < file_systems.size(); ++i)
-    file_system_value.Append(CreateFileSystemValue(file_systems[i]));
+  for (const auto& file_system : file_systems)
+    file_system_value.Append(CreateFileSystemValue(file_system));
   web_contents_->CallClientFunction("DevToolsAPI.fileSystemsLoaded",
                                     &file_system_value, nullptr, nullptr);
 }
@@ -610,9 +610,8 @@ void CommonWebContentsDelegate::OnDevToolsSearchCompleted(
     const std::string& file_system_path,
     const std::vector<std::string>& file_paths) {
   base::ListValue file_paths_value;
-  for (std::vector<std::string>::const_iterator it(file_paths.begin());
-       it != file_paths.end(); ++it) {
-    file_paths_value.AppendString(*it);
+  for (const auto& file_path : file_paths) {
+    file_paths_value.AppendString(file_path);
   }
   base::FundamentalValue request_id_value(request_id);
   base::StringValue file_system_path_value(file_system_path);

+ 5 - 0
atom/browser/common_web_contents_delegate_mac.mm

@@ -27,6 +27,11 @@ void CommonWebContentsDelegate::HandleKeyboardEvent(
   if (event.windowsKeyCode == ui::VKEY_ESCAPE && is_html_fullscreen())
     ExitFullscreenModeForTab(source);
 
+  // Send the event to the menu before sending it to the window
+  if (event.os_event.type == NSKeyDown &&
+      [[NSApp mainMenu] performKeyEquivalent:event.os_event])
+    return;
+
   if (event.os_event.window)
     [event.os_event.window redispatchKeyEvent:event.os_event];
 }

+ 2 - 0
atom/browser/mac/atom_application.mm

@@ -83,6 +83,8 @@
   } else {
     ax_state->DisableAccessibility();
   }
+
+  atom::Browser::Get()->OnAccessibilitySupportChanged();
 }
 
 @end

+ 1 - 3
atom/browser/mac/atom_application_delegate.h

@@ -11,9 +11,7 @@
   base::scoped_nsobject<AtomMenuController> menu_controller_;
 }
 
-- (id)init;
-
 // Sets the menu that will be returned in "applicationDockMenu:".
-- (void)setApplicationDockMenu:(ui::MenuModel*)model;
+- (void)setApplicationDockMenu:(atom::AtomMenuModel*)model;
 
 @end

+ 7 - 9
atom/browser/mac/atom_application_delegate.mm

@@ -12,14 +12,9 @@
 
 @implementation AtomApplicationDelegate
 
-- (id)init {
-  self = [super init];
-  menu_controller_.reset([[AtomMenuController alloc] init]);
-  return self;
-}
-
-- (void)setApplicationDockMenu:(ui::MenuModel*)model {
-  [menu_controller_ populateWithModel:model];
+- (void)setApplicationDockMenu:(atom::AtomMenuModel*)model {
+  menu_controller_.reset([[AtomMenuController alloc] initWithModel:model
+                                             useDefaultAccelerator:NO]);
 }
 
 - (void)applicationWillFinishLaunching:(NSNotification*)notify {
@@ -34,7 +29,10 @@
 }
 
 - (NSMenu*)applicationDockMenu:(NSApplication*)sender {
-  return [menu_controller_ menu];
+  if (menu_controller_)
+    return [menu_controller_ menu];
+  else
+    return nil;
 }
 
 - (BOOL)application:(NSApplication*)sender

+ 4 - 47
atom/browser/native_window.cc

@@ -11,6 +11,7 @@
 #include "atom/browser/atom_browser_context.h"
 #include "atom/browser/atom_browser_main_parts.h"
 #include "atom/browser/browser.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "atom/browser/window_list.h"
 #include "atom/common/api/api_messages.h"
 #include "atom/common/native_mate_converters/file_path_converter.h"
@@ -53,7 +54,6 @@ NativeWindow::NativeWindow(
       transparent_(false),
       enable_larger_than_screen_(false),
       is_closed_(false),
-      has_dialog_attached_(false),
       sheet_offset_x_(0.0),
       sheet_offset_y_(0.0),
       aspect_ratio_(0.0),
@@ -210,7 +210,7 @@ gfx::Size NativeWindow::GetContentSize() {
 
 void NativeWindow::SetSizeConstraints(
     const extensions::SizeConstraints& window_constraints) {
-  extensions::SizeConstraints content_constraints;
+  extensions::SizeConstraints content_constraints(GetContentSizeConstraints());
   if (window_constraints.HasMaximumSize())
     content_constraints.set_maximum_size(
         WindowSizeToContentSize(window_constraints.GetMaximumSize()));
@@ -291,11 +291,7 @@ bool NativeWindow::IsDocumentEdited() {
 void NativeWindow::SetFocusable(bool focusable) {
 }
 
-void NativeWindow::SetMenu(ui::MenuModel* menu) {
-}
-
-bool NativeWindow::HasModalDialog() {
-  return has_dialog_attached_;
+void NativeWindow::SetMenu(AtomMenuModel* menu) {
 }
 
 void NativeWindow::SetParentWindow(NativeWindow* parent) {
@@ -315,39 +311,6 @@ bool NativeWindow::IsWebViewFocused() {
   return host_view && host_view->HasFocus();
 }
 
-void NativeWindow::CapturePage(const gfx::Rect& rect,
-                               const CapturePageCallback& callback) {
-  const auto view = web_contents()->GetRenderWidgetHostView();
-  const auto host = view ? view->GetRenderWidgetHost() : nullptr;
-  if (!view || !host) {
-    callback.Run(SkBitmap());
-    return;
-  }
-
-  // Capture full page if user doesn't specify a |rect|.
-  const gfx::Size view_size = rect.IsEmpty() ? view->GetViewBounds().size() :
-                                               rect.size();
-
-  // By default, the requested bitmap size is the view size in screen
-  // coordinates.  However, if there's more pixel detail available on the
-  // current system, increase the requested bitmap size to capture it all.
-  gfx::Size bitmap_size = view_size;
-  const gfx::NativeView native_view = view->GetNativeView();
-  const float scale =
-      display::Screen::GetScreen()->GetDisplayNearestWindow(native_view)
-      .device_scale_factor();
-  if (scale > 1.0f)
-    bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
-
-  host->CopyFromBackingStore(
-      gfx::Rect(rect.origin(), view_size),
-      bitmap_size,
-      base::Bind(&NativeWindow::OnCapturePageDone,
-                 weak_factory_.GetWeakPtr(),
-                 callback),
-      kBGRA_8888_SkColorType);
-}
-
 void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
 }
 
@@ -624,7 +587,7 @@ void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
 void NativeWindow::NotifyWindowUnresponsive() {
   window_unresposive_closure_.Cancel();
 
-  if (!is_closed_ && !HasModalDialog() && IsEnabled())
+  if (!is_closed_ && !IsUnresponsiveEventSuppressed() && IsEnabled())
     FOR_EACH_OBSERVER(NativeWindowObserver,
                       observers_,
                       OnRendererUnresponsive());
@@ -634,10 +597,4 @@ void NativeWindow::NotifyReadyToShow() {
   FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnReadyToShow());
 }
 
-void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
-                                     const SkBitmap& bitmap,
-                                     content::ReadbackResponse response) {
-  callback.Run(bitmap);
-}
-
 }  // namespace atom

+ 3 - 45
atom/browser/native_window.h

@@ -12,6 +12,7 @@
 
 #include "atom/browser/native_window_observer.h"
 #include "atom/browser/ui/accelerator_util.h"
+#include "atom/browser/ui/atom_menu_model.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -43,10 +44,6 @@ namespace mate {
 class Dictionary;
 }
 
-namespace ui {
-class MenuModel;
-}
-
 namespace atom {
 
 struct DraggableRegion;
@@ -54,28 +51,7 @@ struct DraggableRegion;
 class NativeWindow : public base::SupportsUserData,
                      public content::WebContentsObserver {
  public:
-  using CapturePageCallback = base::Callback<void(const SkBitmap& bitmap)>;
-
-  class DialogScope {
-   public:
-    explicit DialogScope(NativeWindow* window)
-        : window_(window) {
-      if (window_ != NULL)
-        window_->set_has_dialog_attached(true);
-    }
-
-    ~DialogScope() {
-      if (window_ != NULL)
-        window_->set_has_dialog_attached(false);
-    }
-
-   private:
-    NativeWindow* window_;
-
-    DISALLOW_COPY_AND_ASSIGN(DialogScope);
-  };
-
-  virtual ~NativeWindow();
+  ~NativeWindow() override;
 
   // Create window with existing WebContents, the caller is responsible for
   // managing the window's live.
@@ -159,8 +135,7 @@ class NativeWindow : public base::SupportsUserData,
   virtual void SetIgnoreMouseEvents(bool ignore) = 0;
   virtual void SetContentProtection(bool enable) = 0;
   virtual void SetFocusable(bool focusable);
-  virtual void SetMenu(ui::MenuModel* menu);
-  virtual bool HasModalDialog();
+  virtual void SetMenu(AtomMenuModel* menu);
   virtual void SetParentWindow(NativeWindow* parent);
   virtual gfx::NativeWindow GetNativeWindow() = 0;
   virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;
@@ -179,11 +154,6 @@ class NativeWindow : public base::SupportsUserData,
   virtual void BlurWebView();
   virtual bool IsWebViewFocused();
 
-  // Captures the page with |rect|, |callback| would be called when capturing is
-  // done.
-  virtual void CapturePage(const gfx::Rect& rect,
-                           const CapturePageCallback& callback);
-
   // Toggle the menu bar.
   virtual void SetAutoHideMenuBar(bool auto_hide);
   virtual bool IsMenuBarAutoHide();
@@ -255,10 +225,6 @@ class NativeWindow : public base::SupportsUserData,
   SkRegion* draggable_region() const { return draggable_region_.get(); }
   bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
 
-  void set_has_dialog_attached(bool has_dialog_attached) {
-    has_dialog_attached_ = has_dialog_attached;
-  }
-
   NativeWindow* parent() const { return parent_; }
   bool is_modal() const { return is_modal_; }
 
@@ -296,11 +262,6 @@ class NativeWindow : public base::SupportsUserData,
   // Dispatch ReadyToShow event to observers.
   void NotifyReadyToShow();
 
-  // Called when CapturePage has done.
-  void OnCapturePageDone(const CapturePageCallback& callback,
-                         const SkBitmap& bitmap,
-                         content::ReadbackResponse response);
-
   // Whether window has standard frame.
   bool has_frame_;
 
@@ -320,9 +281,6 @@ class NativeWindow : public base::SupportsUserData,
   // The windows has been closed.
   bool is_closed_;
 
-  // There is a dialog that has been attached to window.
-  bool has_dialog_attached_;
-
   // 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_unresposive_closure_;

+ 0 - 1
atom/browser/native_window_mac.h

@@ -80,7 +80,6 @@ class NativeWindowMac : public NativeWindow {
   bool IsDocumentEdited() override;
   void SetIgnoreMouseEvents(bool ignore) override;
   void SetContentProtection(bool enable) override;
-  bool HasModalDialog() override;
   void SetParentWindow(NativeWindow* parent) override;
   gfx::NativeWindow GetNativeWindow() override;
   gfx::AcceleratedWidget GetAcceleratedWidget() override;

+ 26 - 22
atom/browser/native_window_mac.mm

@@ -241,13 +241,6 @@ bool ScopedDisableResize::disable_resize_ = false;
 }
 
 - (void)windowDidExitFullScreen:(NSNotification*)notification {
-  // For certain versions of macOS the fullscreen button will automatically show
-  // after exiting fullscreen mode.
-  if (!shell_->has_frame()) {
-    NSWindow* window = shell_->GetNativeWindow();
-    [[window standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
-  }
-
   shell_->NotifyWindowLeaveFullScreen();
 }
 
@@ -732,13 +725,22 @@ bool NativeWindowMac::IsFullscreen() const {
 }
 
 void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
-  NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0,
-                                   bounds.width(),
-                                   bounds.height());
+  // Do nothing if in fullscreen mode.
+  if (IsFullscreen())
+    return;
+
+  // Check size constraints since setFrame does not check it.
+  gfx::Size size = bounds.size();
+  size.SetToMax(GetMinimumSize());
+  gfx::Size max_size = GetMaximumSize();
+  if (!max_size.IsEmpty())
+    size.SetToMin(max_size);
+
+  NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0, size.width(), size.height());
   // Flip coordinates based on the primary screen.
   NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
   cocoa_bounds.origin.y =
-      NSHeight([screen frame]) - bounds.height() - bounds.y();
+      NSHeight([screen frame]) - size.height() - bounds.y();
 
   [window_ setFrame:cocoa_bounds display:YES animate:animate];
 }
@@ -790,13 +792,13 @@ bool NativeWindowMac::IsResizable() {
 
 void NativeWindowMac::SetAspectRatio(double aspect_ratio,
                                      const gfx::Size& extra_size) {
-    NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
+  NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
 
-    // Reset the behaviour to default if aspect_ratio is set to 0 or less.
-    if (aspect_ratio > 0.0)
-      [window_ setAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
-    else
-      [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
+  // Reset the behaviour to default if aspect_ratio is set to 0 or less.
+  if (aspect_ratio > 0.0)
+    [window_ setAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
+  else
+    [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
 }
 
 void NativeWindowMac::SetMovable(bool movable) {
@@ -950,10 +952,6 @@ void NativeWindowMac::SetContentProtection(bool enable) {
                                  : NSWindowSharingReadOnly];
 }
 
-bool NativeWindowMac::HasModalDialog() {
-  return [window_ attachedSheet] != nil;
-}
-
 void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
   if (is_modal())
     return;
@@ -1072,7 +1070,10 @@ void NativeWindowMac::UpdateDraggableRegions(
 
 void NativeWindowMac::InstallView() {
   // Make sure the bottom corner is rounded: http://crbug.com/396264.
-  [[window_ contentView] setWantsLayer:YES];
+  // But do not enable it on OS X 10.9 for transparent window, otherwise a
+  // semi-transparent frame would show.
+  if (!(transparent() && base::mac::IsOSMavericks()))
+    [[window_ contentView] setWantsLayer:YES];
 
   NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
   if (has_frame()) {
@@ -1092,6 +1093,9 @@ void NativeWindowMac::InstallView() {
     [view setFrame:[content_view_ bounds]];
     [content_view_ addSubview:view];
 
+    // The fullscreen button should always be hidden for frameless window.
+    [[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
+
     if (title_bar_style_ != NORMAL)
       return;
 

+ 76 - 22
atom/browser/native_window_views.cc

@@ -23,6 +23,7 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/screen.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
 #include "ui/views/controls/webview/webview.h"
@@ -135,6 +136,10 @@ NativeWindowViews::NativeWindowViews(
       menu_bar_autohide_(false),
       menu_bar_visible_(false),
       menu_bar_alt_pressed_(false),
+#if defined(OS_WIN)
+      enabled_a11y_support_(false),
+      thick_frame_(true),
+#endif
       keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
       disable_count_(0),
       use_content_size_(false),
@@ -152,6 +157,11 @@ NativeWindowViews::NativeWindowViews(
   options.Get(options::kResizable, &resizable_);
   options.Get(options::kMinimizable, &minimizable_);
   options.Get(options::kMaximizable, &maximizable_);
+
+  // Transparent window must not have thick frame.
+  options.Get("thickFrame", &thick_frame_);
+  if (transparent())
+    thick_frame_ = false;
 #endif
 
   if (enable_larger_than_screen())
@@ -214,6 +224,9 @@ NativeWindowViews::NativeWindowViews(
   bool fullscreen = false;
   options.Get(options::kFullscreen, &fullscreen);
 
+  std::string window_type;
+  options.Get(options::kType, &window_type);
+
 #if defined(USE_X11)
   // Start monitoring window states.
   window_state_watcher_.reset(new WindowStateWatcher(this));
@@ -243,9 +256,6 @@ NativeWindowViews::NativeWindowViews(
     state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN"));
   }
 
-  std::string window_type;
-  options.Get(options::kType, &window_type);
-
   if (parent) {
     SetParentWindow(parent);
     // Force using dialog type for child window.
@@ -269,13 +279,6 @@ NativeWindowViews::NativeWindowViews(
   AddChildView(web_view_);
 
 #if defined(OS_WIN)
-  // Save initial window state.
-  if (fullscreen)
-    last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
-  else
-    last_window_state_ = ui::SHOW_STATE_NORMAL;
-  last_normal_size_ = gfx::Size(widget_size_);
-
   if (!has_frame()) {
     // Set Window style so that we get a minimize and maximize animation when
     // frameless.
@@ -287,17 +290,18 @@ NativeWindowViews::NativeWindowViews(
     if (maximizable_)
       frame_style |= WS_MAXIMIZEBOX;
     // We should not show a frame for transparent window.
-    if (transparent())
+    if (!thick_frame_)
       frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
     ::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
   }
 
-  if (transparent()) {
-    // Transparent window on Windows has to have WS_EX_COMPOSITED style.
-    LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
+  LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
+  // Window without thick frame has to have WS_EX_COMPOSITED style.
+  if (!thick_frame_)
     ex_style |= WS_EX_COMPOSITED;
-    ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
-  }
+  if (window_type == "toolbar")
+    ex_style |= WS_EX_TOOLWINDOW;
+  ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
 #endif
 
   // TODO(zcbenz): This was used to force using native frame on Windows 2003, we
@@ -315,6 +319,15 @@ NativeWindowViews::NativeWindowViews(
 
   window_->CenterWindow(size);
   Layout();
+
+#if defined(OS_WIN)
+  // Save initial window state.
+  if (fullscreen)
+    last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
+  else
+    last_window_state_ = ui::SHOW_STATE_NORMAL;
+  last_normal_bounds_ = GetBounds();
+#endif
 }
 
 NativeWindowViews::~NativeWindowViews() {
@@ -410,6 +423,17 @@ bool NativeWindowViews::IsEnabled() {
 }
 
 void NativeWindowViews::Maximize() {
+#if defined(OS_WIN)
+  // For window without WS_THICKFRAME style, we can not call Maximize().
+  if (!thick_frame_) {
+    restore_bounds_ = GetBounds();
+    auto display =
+        gfx::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
+    SetBounds(display.work_area(), false);
+    return;
+  }
+#endif
+
   if (IsVisible())
     window_->Maximize();
   else
@@ -418,6 +442,13 @@ void NativeWindowViews::Maximize() {
 }
 
 void NativeWindowViews::Unmaximize() {
+#if defined(OS_WIN)
+  if (!thick_frame_) {
+    SetBounds(restore_bounds_, false);
+    return;
+  }
+#endif
+
   window_->Restore();
 }
 
@@ -454,6 +485,20 @@ void NativeWindowViews::SetFullScreen(bool fullscreen) {
     last_window_state_ = ui::SHOW_STATE_NORMAL;
     NotifyWindowLeaveFullScreen();
   }
+
+  // For window without WS_THICKFRAME style, we can not call SetFullscreen().
+  if (!thick_frame_) {
+    if (fullscreen) {
+      restore_bounds_ = GetBounds();
+      auto display =
+          gfx::Screen::GetScreen()->GetDisplayNearestPoint(GetPosition());
+      SetBounds(display.bounds(), false);
+    } else {
+      SetBounds(restore_bounds_, false);
+    }
+    return;
+  }
+
   // We set the new value after notifying, so we can handle the size event
   // correctly.
   window_->SetFullscreen(fullscreen);
@@ -463,6 +508,12 @@ void NativeWindowViews::SetFullScreen(bool fullscreen) {
   else
     window_->native_widget_private()->ShowWithWindowState(
         ui::SHOW_STATE_FULLSCREEN);
+
+  // Auto-hide menubar when in fullscreen.
+  if (fullscreen)
+    SetMenuBarVisibility(false);
+  else
+    SetMenuBarVisibility(!menu_bar_autohide_);
 #endif
 }
 
@@ -470,8 +521,7 @@ bool NativeWindowViews::IsFullscreen() const {
   return window_->IsFullscreen();
 }
 
-void NativeWindowViews::SetBounds(const gfx::Rect& bounds,
-    bool animate = false) {
+void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
 #if defined(USE_X11)
   // On Linux the minimum and maximum size should be updated with window size
   // when window is not resizable.
@@ -517,7 +567,7 @@ void NativeWindowViews::SetContentSizeConstraints(
 
 void NativeWindowViews::SetResizable(bool resizable) {
 #if defined(OS_WIN)
-  if (!transparent())
+  if (thick_frame_)
     FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
 #elif defined(USE_X11)
   if (resizable != resizable_) {
@@ -540,7 +590,11 @@ void NativeWindowViews::SetResizable(bool resizable) {
 
 bool NativeWindowViews::IsResizable() {
 #if defined(OS_WIN)
-  return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
+  if (thick_frame_) {
+    return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
+  } else {
+    return CanResize();
+  }
 #else
   return CanResize();
 #endif
@@ -752,7 +806,7 @@ void NativeWindowViews::SetFocusable(bool focusable) {
 #endif
 }
 
-void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
+void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
   if (menu_model == nullptr) {
     // Remove accelerators
     accelerator_table_.clear();
@@ -1188,7 +1242,7 @@ bool NativeWindowViews::AcceleratorPressed(const ui::Accelerator& accelerator) {
       &accelerator_table_, accelerator);
 }
 
-void NativeWindowViews::RegisterAccelerators(ui::MenuModel* menu_model) {
+void NativeWindowViews::RegisterAccelerators(AtomMenuModel* menu_model) {
   // Clear previous accelerators.
   views::FocusManager* focus_manager = GetFocusManager();
   accelerator_table_.clear();

+ 9 - 3
atom/browser/native_window_views.h

@@ -98,7 +98,7 @@ class NativeWindowViews : public NativeWindow,
   void SetIgnoreMouseEvents(bool ignore) override;
   void SetContentProtection(bool enable) override;
   void SetFocusable(bool focusable) override;
-  void SetMenu(ui::MenuModel* menu_model) override;
+  void SetMenu(AtomMenuModel* menu_model) override;
   void SetParentWindow(NativeWindow* parent) override;
   gfx::NativeWindow GetNativeWindow() override;
   void SetOverlayIcon(const gfx::Image& overlay,
@@ -176,7 +176,7 @@ class NativeWindowViews : public NativeWindow,
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
   // Register accelerators supported by the menu model.
-  void RegisterAccelerators(ui::MenuModel* menu_model);
+  void RegisterAccelerators(AtomMenuModel* menu_model);
 
   // Returns the restore state for the window.
   ui::WindowShowState GetRestoredState();
@@ -212,7 +212,7 @@ class NativeWindowViews : public NativeWindow,
   // to receive the wrong size (#2498). To circumvent that, we keep tabs on the
   // size of the window while in the normal state (not maximized, minimized or
   // fullscreen), so we restore it correctly.
-  gfx::Size last_normal_size_;
+  gfx::Rect last_normal_bounds_;
 
   // In charge of running taskbar related APIs.
   TaskbarHost taskbar_host_;
@@ -220,6 +220,12 @@ class NativeWindowViews : public NativeWindow,
   // If true we have enabled a11y
   bool enabled_a11y_support_;
 
+  // Whether to show the WS_THICKFRAME style.
+  bool thick_frame_;
+
+  // The bounds of window before maximize/fullscreen.
+  gfx::Rect restore_bounds_;
+
   // The icons of window and taskbar.
   base::win::ScopedHICON window_icon_;
   base::win::ScopedHICON app_icon_;

+ 5 - 3
atom/browser/native_window_views_win.cc

@@ -2,6 +2,7 @@
 // Use of this source code is governed by the MIT license that can be
 // found in the LICENSE file.
 
+#include "atom/browser/browser.h"
 #include "atom/browser/native_window_views.h"
 #include "content/public/browser/browser_accessibility_state.h"
 
@@ -98,6 +99,7 @@ bool NativeWindowViews::PreHandleMSG(
         if (axState && !axState->IsAccessibleBrowser()) {
           axState->OnScreenReaderDetected();
           enabled_a11y_support_ = true;
+          Browser::Get()->OnAccessibilitySupportChanged();
         }
       }
 
@@ -140,7 +142,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
     case SIZE_RESTORED:
       if (last_window_state_ == ui::SHOW_STATE_NORMAL) {
         // Window was resized so we save it's new size.
-        last_normal_size_ = GetSize();
+        last_normal_bounds_ = GetBounds();
       } else {
         switch (last_window_state_) {
           case ui::SHOW_STATE_MAXIMIZED:
@@ -148,7 +150,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
 
             // When the window is restored we resize it to the previous known
             // normal size.
-            NativeWindow::SetSize(last_normal_size_);
+            SetBounds(last_normal_bounds_, false);
 
             NotifyWindowUnmaximize();
             break;
@@ -161,7 +163,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
 
               // When the window is restored we resize it to the previous known
               // normal size.
-              NativeWindow::SetSize(last_normal_size_);
+              SetBounds(last_normal_bounds_, false);
 
               NotifyWindowRestore();
             }

+ 1 - 1
atom/browser/net/asar/asar_protocol_handler.cc

@@ -22,7 +22,7 @@ net::URLRequestJob* AsarProtocolHandler::MaybeCreateJob(
     net::NetworkDelegate* network_delegate) const {
   base::FilePath full_path;
   net::FileURLToFilePath(request->url(), &full_path);
-  URLRequestAsarJob* job = new URLRequestAsarJob(request, network_delegate);
+  auto* job = new URLRequestAsarJob(request, network_delegate);
   job->Initialize(file_task_runner_, full_path);
   return job;
 }

+ 3 - 3
atom/browser/net/asar/url_request_asar_job.cc

@@ -111,7 +111,7 @@ void URLRequestAsarJob::Start() {
     if (rv != net::ERR_IO_PENDING)
       DidOpen(rv);
   } else if (type_ == TYPE_FILE) {
-    FileMetaInfo* meta_info = new FileMetaInfo();
+    auto* meta_info = new FileMetaInfo();
     file_task_runner_->PostTaskAndReply(
         FROM_HERE,
         base::Bind(&URLRequestAsarJob::FetchMetaInfo, file_path_,
@@ -224,7 +224,7 @@ int URLRequestAsarJob::GetResponseCode() const {
 
 void URLRequestAsarJob::GetResponseInfo(net::HttpResponseInfo* info) {
   std::string status("HTTP/1.1 200 OK");
-  net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
+  auto* headers = new net::HttpResponseHeaders(status);
 
   headers->AddHeader(atom::kCORSHeader);
   info->headers = headers;
@@ -338,7 +338,7 @@ void URLRequestAsarJob::DidRead(scoped_refptr<net::IOBuffer> buf, int result) {
     DCHECK_GE(remaining_bytes_, 0);
   }
 
-  buf = NULL;
+  buf = nullptr;
 
   ReadRawDataComplete(result);
 }

+ 2 - 9
atom/browser/net/atom_cert_verifier.cc

@@ -36,7 +36,6 @@ AtomCertVerifier::~AtomCertVerifier() {
 }
 
 void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) {
-  base::AutoLock auto_lock(lock_);
   verify_proc_ = proc;
 }
 
@@ -52,20 +51,14 @@ int AtomCertVerifier::Verify(
     const net::BoundNetLog& net_log) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  VerifyProc proc;
-  {
-    base::AutoLock auto_lock(lock_);
-    proc = verify_proc_;
-  }
-
-  if (proc.is_null())
+  if (verify_proc_.is_null())
     return default_cert_verifier_->Verify(
         cert, hostname, ocsp_response, flags, crl_set, verify_result, callback,
         out_req, net_log);
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(proc, hostname, make_scoped_refptr(cert),
+      base::Bind(verify_proc_, hostname, make_scoped_refptr(cert),
                  base::Bind(OnResult, verify_result, callback)));
   return net::ERR_IO_PENDING;
 }

+ 1 - 3
atom/browser/net/atom_cert_verifier.h

@@ -5,10 +5,9 @@
 #ifndef ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_
 #define ATOM_BROWSER_NET_ATOM_CERT_VERIFIER_H_
 
+#include <memory>
 #include <string>
 
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
 #include "net/cert/cert_verifier.h"
 
 namespace atom {
@@ -39,7 +38,6 @@ class AtomCertVerifier : public net::CertVerifier {
   bool SupportsOCSPStapling() override;
 
  private:
-  base::Lock lock_;
   VerifyProc verify_proc_;
   std::unique_ptr<net::CertVerifier> default_cert_verifier_;
 

+ 8 - 4
atom/browser/net/atom_url_request_job_factory.cc

@@ -20,14 +20,14 @@ typedef net::URLRequestJobFactory::ProtocolHandler ProtocolHandler;
 AtomURLRequestJobFactory::AtomURLRequestJobFactory() {}
 
 AtomURLRequestJobFactory::~AtomURLRequestJobFactory() {
-  STLDeleteValues(&protocol_handler_map_);
+  Clear();
 }
 
 bool AtomURLRequestJobFactory::SetProtocolHandler(
     const std::string& scheme,
     std::unique_ptr<ProtocolHandler> protocol_handler) {
   if (!protocol_handler) {
-    ProtocolHandlerMap::iterator it = protocol_handler_map_.find(scheme);
+    auto it = protocol_handler_map_.find(scheme);
     if (it == protocol_handler_map_.end())
       return false;
 
@@ -66,7 +66,7 @@ ProtocolHandler* AtomURLRequestJobFactory::GetProtocolHandler(
     const std::string& scheme) const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  ProtocolHandlerMap::const_iterator it = protocol_handler_map_.find(scheme);
+  auto it = protocol_handler_map_.find(scheme);
   if (it == protocol_handler_map_.end())
     return nullptr;
   return it->second;
@@ -77,13 +77,17 @@ bool AtomURLRequestJobFactory::HasProtocolHandler(
   return ContainsKey(protocol_handler_map_, scheme);
 }
 
+void AtomURLRequestJobFactory::Clear() {
+  STLDeleteValues(&protocol_handler_map_);
+}
+
 net::URLRequestJob* AtomURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
     const std::string& scheme,
     net::URLRequest* request,
     net::NetworkDelegate* network_delegate) const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  ProtocolHandlerMap::const_iterator it = protocol_handler_map_.find(scheme);
+  auto it = protocol_handler_map_.find(scheme);
   if (it == protocol_handler_map_.end())
     return nullptr;
   return it->second->MaybeCreateJob(request, network_delegate);

+ 3 - 0
atom/browser/net/atom_url_request_job_factory.h

@@ -39,6 +39,9 @@ class AtomURLRequestJobFactory : public net::URLRequestJobFactory {
   // Whether the protocol handler is registered by the job factory.
   bool HasProtocolHandler(const std::string& scheme) const;
 
+  // Clear all protocol handlers.
+  void Clear();
+
   // URLRequestJobFactory implementation
   net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
       const std::string& scheme,

+ 1 - 1
atom/browser/net/url_request_async_asar_job.cc

@@ -40,7 +40,7 @@ void URLRequestAsyncAsarJob::StartAsync(std::unique_ptr<base::Value> options) {
 
 void URLRequestAsyncAsarJob::GetResponseInfo(net::HttpResponseInfo* info) {
   std::string status("HTTP/1.1 200 OK");
-  net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
+  auto* headers = new net::HttpResponseHeaders(status);
 
   headers->AddHeader(kCORSHeader);
   info->headers = headers;

+ 1 - 1
atom/browser/net/url_request_buffer_job.cc

@@ -72,7 +72,7 @@ void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) {
   status.append(" ");
   status.append(net::GetHttpReasonPhrase(status_code_));
   status.append("\0\0", 2);
-  net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
+  auto* headers = new net::HttpResponseHeaders(status);
 
   headers->AddHeader(kCORSHeader);
 

+ 1 - 1
atom/browser/net/url_request_string_job.cc

@@ -31,7 +31,7 @@ void URLRequestStringJob::StartAsync(std::unique_ptr<base::Value> options) {
 
 void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) {
   std::string status("HTTP/1.1 200 OK");
-  net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
+  auto* headers = new net::HttpResponseHeaders(status);
 
   headers->AddHeader(kCORSHeader);
 

+ 10 - 0
atom/browser/relauncher_linux.cc

@@ -4,11 +4,13 @@
 
 #include "atom/browser/relauncher.h"
 
+#include <fcntl.h>
 #include <signal.h>
 #include <sys/prctl.h>
 #include <sys/signalfd.h>
 
 #include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
@@ -55,9 +57,17 @@ void RelauncherSynchronizeWithParent() {
 
 int LaunchProgram(const StringVector& relauncher_args,
                   const StringVector& argv) {
+  // Redirect the stdout of child process to /dev/null, otherwise after
+  // relaunch the child process will raise exception when writing to stdout.
+  base::ScopedFD devnull(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
+  base::FileHandleMappingVector no_stdout;
+  no_stdout.push_back(std::make_pair(devnull.get(), STDERR_FILENO));
+  no_stdout.push_back(std::make_pair(devnull.get(), STDOUT_FILENO));
+
   base::LaunchOptions options;
   options.allow_new_privs = true;
   options.new_process_group = true;  // detach
+  options.fds_to_remap = &no_stdout;
   base::Process process = base::LaunchProcess(argv, options);
   return process.IsValid() ? 0 : 1;
 }

+ 10 - 2
atom/browser/relauncher_mac.cc

@@ -43,7 +43,7 @@ void RelauncherSynchronizeWithParent() {
 
   struct kevent change = { 0 };
   EV_SET(&change, parent_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
-  if (kevent(kq.get(), &change, 1, NULL, 0, NULL) == -1) {
+  if (kevent(kq.get(), &change, 1, nullptr, 0, nullptr) == -1) {
     PLOG(ERROR) << "kevent (add)";
     return;
   }
@@ -58,7 +58,7 @@ void RelauncherSynchronizeWithParent() {
   // write above to complete. The parent process is now free to exit. Wait for
   // that to happen.
   struct kevent event;
-  int events = kevent(kq.get(), NULL, 0, &event, 1, NULL);
+  int events = kevent(kq.get(), nullptr, 0, &event, 1, nullptr);
   if (events != 1) {
     if (events < 0) {
       PLOG(ERROR) << "kevent (monitor)";
@@ -79,8 +79,16 @@ void RelauncherSynchronizeWithParent() {
 
 int LaunchProgram(const StringVector& relauncher_args,
                   const StringVector& argv) {
+  // Redirect the stdout of child process to /dev/null, otherwise after
+  // relaunch the child process will raise exception when writing to stdout.
+  base::ScopedFD devnull(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
+  base::FileHandleMappingVector no_stdout;
+  no_stdout.push_back(std::make_pair(devnull.get(), STDERR_FILENO));
+  no_stdout.push_back(std::make_pair(devnull.get(), STDOUT_FILENO));
+
   base::LaunchOptions options;
   options.new_process_group = true;  // detach
+  options.fds_to_remap = &no_stdout;
   base::Process process = base::LaunchProcess(argv, options);
   return process.IsValid() ? 0 : 1;
 }

+ 2 - 2
atom/browser/resources/mac/Info.plist

@@ -17,9 +17,9 @@
   <key>CFBundleIconFile</key>
   <string>electron.icns</string>
   <key>CFBundleVersion</key>
-  <string>1.2.5</string>
+  <string>1.2.8</string>
   <key>CFBundleShortVersionString</key>
-  <string>1.2.5</string>
+  <string>1.2.8</string>
   <key>LSApplicationCategoryType</key>
   <string>public.app-category.developer-tools</string>
   <key>LSMinimumSystemVersion</key>

+ 4 - 4
atom/browser/resources/win/atom.rc

@@ -56,8 +56,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,2,5,0
- PRODUCTVERSION 1,2,5,0
+ FILEVERSION 1,2,8,0
+ PRODUCTVERSION 1,2,8,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -74,12 +74,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "GitHub, Inc."
             VALUE "FileDescription", "Electron"
-            VALUE "FileVersion", "1.2.5"
+            VALUE "FileVersion", "1.2.8"
             VALUE "InternalName", "electron.exe"
             VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
             VALUE "OriginalFilename", "electron.exe"
             VALUE "ProductName", "Electron"
-            VALUE "ProductVersion", "1.2.5"
+            VALUE "ProductVersion", "1.2.8"
             VALUE "SquirrelAwareVersion", "1"
         END
     END

+ 8 - 8
atom/browser/ui/accelerator_util.cc

@@ -14,7 +14,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "ui/base/models/simple_menu_model.h"
 
 namespace accelerator_util {
 
@@ -31,9 +30,9 @@ bool StringToAccelerator(const std::string& shortcut,
   // Now, parse it into an accelerator.
   int modifiers = ui::EF_NONE;
   ui::KeyboardCode key = ui::VKEY_UNKNOWN;
-  for (size_t i = 0; i < tokens.size(); i++) {
+  for (const auto& token : tokens) {
     bool shifted = false;
-    ui::KeyboardCode code = atom::KeyboardCodeFromStr(tokens[i], &shifted);
+    ui::KeyboardCode code = atom::KeyboardCodeFromStr(token, &shifted);
     if (shifted)
       modifiers |= ui::EF_SHIFT_DOWN;
     switch (code) {
@@ -69,16 +68,17 @@ bool StringToAccelerator(const std::string& shortcut,
   return true;
 }
 
-void GenerateAcceleratorTable(AcceleratorTable* table, ui::MenuModel* model) {
+void GenerateAcceleratorTable(AcceleratorTable* table,
+                              atom::AtomMenuModel* model) {
   int count = model->GetItemCount();
   for (int i = 0; i < count; ++i) {
-    ui::MenuModel::ItemType type = model->GetTypeAt(i);
-    if (type == ui::MenuModel::TYPE_SUBMENU) {
-      ui::MenuModel* submodel = model->GetSubmenuModelAt(i);
+    atom::AtomMenuModel::ItemType type = model->GetTypeAt(i);
+    if (type == atom::AtomMenuModel::TYPE_SUBMENU) {
+      auto submodel = model->GetSubmenuModelAt(i);
       GenerateAcceleratorTable(table, submodel);
     } else {
       ui::Accelerator accelerator;
-      if (model->GetAcceleratorAt(i, &accelerator)) {
+      if (model->GetAcceleratorAtWithParams(i, true, &accelerator)) {
         MenuItem item = { i, model };
         (*table)[accelerator] = item;
       }

+ 4 - 6
atom/browser/ui/accelerator_util.h

@@ -8,15 +8,12 @@
 #include <map>
 #include <string>
 
+#include "atom/browser/ui/atom_menu_model.h"
 #include "ui/base/accelerators/accelerator.h"
 
-namespace ui {
-class MenuModel;
-}
-
 namespace accelerator_util {
 
-typedef struct { int position; ui::MenuModel* model; } MenuItem;
+typedef struct { int position; atom::AtomMenuModel* model; } MenuItem;
 typedef std::map<ui::Accelerator, MenuItem> AcceleratorTable;
 
 // Parse a string as an accelerator.
@@ -27,7 +24,8 @@ bool StringToAccelerator(const std::string& description,
 void SetPlatformAccelerator(ui::Accelerator* accelerator);
 
 // Generate a table that contains memu model's accelerators and command ids.
-void GenerateAcceleratorTable(AcceleratorTable* table, ui::MenuModel* model);
+void GenerateAcceleratorTable(AcceleratorTable* table,
+                              atom::AtomMenuModel* model);
 
 // Trigger command from the accelerators table.
 bool TriggerAcceleratorTableCommand(AcceleratorTable* table,

+ 16 - 0
atom/browser/ui/atom_menu_model.cc

@@ -29,9 +29,25 @@ base::string16 AtomMenuModel::GetRoleAt(int index) {
     return base::string16();
 }
 
+bool AtomMenuModel::GetAcceleratorAtWithParams(
+    int index,
+    bool use_default_accelerator,
+    ui::Accelerator* accelerator) const {
+  if (delegate_) {
+    return delegate_->GetAcceleratorForCommandIdWithParams(
+        GetCommandIdAt(index), use_default_accelerator, accelerator);
+  }
+  return false;
+}
+
 void AtomMenuModel::MenuClosed() {
   ui::SimpleMenuModel::MenuClosed();
   FOR_EACH_OBSERVER(Observer, observers_, MenuClosed());
 }
 
+AtomMenuModel* AtomMenuModel::GetSubmenuModelAt(int index) {
+  return static_cast<AtomMenuModel*>(
+      ui::SimpleMenuModel::GetSubmenuModelAt(index));
+}
+
 }  // namespace atom

+ 19 - 0
atom/browser/ui/atom_menu_model.h

@@ -17,6 +17,19 @@ class AtomMenuModel : public ui::SimpleMenuModel {
   class Delegate : public ui::SimpleMenuModel::Delegate {
    public:
     virtual ~Delegate() {}
+
+    virtual bool GetAcceleratorForCommandIdWithParams(
+        int command_id,
+        bool use_default_accelerator,
+        ui::Accelerator* accelerator) const = 0;
+
+   private:
+    // ui::SimpleMenuModel::Delegate:
+    bool GetAcceleratorForCommandId(int command_id,
+                                    ui::Accelerator* accelerator) {
+      return GetAcceleratorForCommandIdWithParams(
+          command_id, false, accelerator);
+    }
   };
 
   class Observer {
@@ -35,10 +48,16 @@ class AtomMenuModel : public ui::SimpleMenuModel {
 
   void SetRole(int index, const base::string16& role);
   base::string16 GetRoleAt(int index);
+  bool GetAcceleratorAtWithParams(int index,
+                                  bool use_default_accelerator,
+                                  ui::Accelerator* accelerator) const;
 
   // ui::SimpleMenuModel:
   void MenuClosed() override;
 
+  using SimpleMenuModel::GetSubmenuModelAt;
+  AtomMenuModel* GetSubmenuModelAt(int index);
+
  private:
   Delegate* delegate_;  // weak ref.
 

+ 7 - 11
atom/browser/ui/cocoa/atom_menu_controller.h

@@ -11,8 +11,8 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/string16.h"
 
-namespace ui {
-class MenuModel;
+namespace atom {
+class AtomMenuModel;
 }
 
 // A controller for the cross-platform menu model. The menu that's created
@@ -23,24 +23,20 @@ class MenuModel;
 // as it only maintains weak references.
 @interface AtomMenuController : NSObject<NSMenuDelegate> {
  @protected
-  ui::MenuModel* model_;  // weak
+  atom::AtomMenuModel* model_;  // weak
   base::scoped_nsobject<NSMenu> menu_;
   BOOL isMenuOpen_;
+  BOOL useDefaultAccelerator_;
 }
 
-@property(nonatomic, assign) ui::MenuModel* model;
-
-// NIB-based initializer. This does not create a menu. Clients can set the
-// properties of the object and the menu will be created upon the first call to
-// |-menu|. Note that the menu will be immutable after creation.
-- (id)init;
+@property(nonatomic, assign) atom::AtomMenuModel* model;
 
 // Builds a NSMenu from the pre-built model (must not be nil). Changes made
 // to the contents of the model after calling this will not be noticed.
-- (id)initWithModel:(ui::MenuModel*)model;
+- (id)initWithModel:(atom::AtomMenuModel*)model useDefaultAccelerator:(BOOL)use;
 
 // Populate current NSMenu with |model|.
-- (void)populateWithModel:(ui::MenuModel*)model;
+- (void)populateWithModel:(atom::AtomMenuModel*)model;
 
 // Programmatically close the constructed menu.
 - (void)cancel;

+ 18 - 22
atom/browser/ui/cocoa/atom_menu_controller.mm

@@ -48,15 +48,11 @@ Role kRolesMap[] = {
 
 @synthesize model = model_;
 
-- (id)init {
-  if ((self = [super init]))
-    [self menu];
-  return self;
-}
-
-- (id)initWithModel:(ui::MenuModel*)model {
+- (id)initWithModel:(atom::AtomMenuModel*)model useDefaultAccelerator:(BOOL)use {
   if ((self = [super init])) {
     model_ = model;
+    isMenuOpen_ = NO;
+    useDefaultAccelerator_ = use;
     [self menu];
   }
   return self;
@@ -73,7 +69,7 @@ Role kRolesMap[] = {
   [super dealloc];
 }
 
-- (void)populateWithModel:(ui::MenuModel*)model {
+- (void)populateWithModel:(atom::AtomMenuModel*)model {
   if (!menu_)
     return;
 
@@ -82,7 +78,7 @@ Role kRolesMap[] = {
 
   const int count = model->GetItemCount();
   for (int index = 0; index < count; index++) {
-    if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR)
+    if (model->GetTypeAt(index) == atom::AtomMenuModel::TYPE_SEPARATOR)
       [self addSeparatorToMenu:menu_ atIndex:index];
     else
       [self addItemToMenu:menu_ atIndex:index fromModel:model];
@@ -99,12 +95,12 @@ Role kRolesMap[] = {
 
 // Creates a NSMenu from the given model. If the model has submenus, this can
 // be invoked recursively.
-- (NSMenu*)menuFromModel:(ui::MenuModel*)model {
+- (NSMenu*)menuFromModel:(atom::AtomMenuModel*)model {
   NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
 
   const int count = model->GetItemCount();
   for (int index = 0; index < count; index++) {
-    if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR)
+    if (model->GetTypeAt(index) == atom::AtomMenuModel::TYPE_SEPARATOR)
       [self addSeparatorToMenu:menu atIndex:index];
     else
       [self addItemToMenu:menu atIndex:index fromModel:model];
@@ -126,9 +122,7 @@ Role kRolesMap[] = {
 // associated with the entry in the model identified by |modelIndex|.
 - (void)addItemToMenu:(NSMenu*)menu
               atIndex:(NSInteger)index
-            fromModel:(ui::MenuModel*)ui_model {
-  atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(ui_model);
-
+            fromModel:(atom::AtomMenuModel*)model {
   base::string16 label16 = model->GetLabelAt(index);
   NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
   base::scoped_nsobject<NSMenuItem> item(
@@ -141,12 +135,13 @@ Role kRolesMap[] = {
   if (model->GetIconAt(index, &icon) && !icon.IsEmpty())
     [item setImage:icon.ToNSImage()];
 
-  ui::MenuModel::ItemType type = model->GetTypeAt(index);
-  if (type == ui::MenuModel::TYPE_SUBMENU) {
+  atom::AtomMenuModel::ItemType type = model->GetTypeAt(index);
+  if (type == atom::AtomMenuModel::TYPE_SUBMENU) {
     // Recursively build a submenu from the sub-model at this index.
     [item setTarget:nil];
     [item setAction:nil];
-    ui::MenuModel* submenuModel = model->GetSubmenuModelAt(index);
+    atom::AtomMenuModel* submenuModel = static_cast<atom::AtomMenuModel*>(
+        model->GetSubmenuModelAt(index));
     NSMenu* submenu = [self menuFromModel:submenuModel];
     [submenu setTitle:[item title]];
     [item setSubmenu:submenu];
@@ -170,7 +165,8 @@ Role kRolesMap[] = {
     NSValue* modelObject = [NSValue valueWithPointer:model];
     [item setRepresentedObject:modelObject];  // Retains |modelObject|.
     ui::Accelerator accelerator;
-    if (model->GetAcceleratorAt(index, &accelerator)) {
+    if (model->GetAcceleratorAtWithParams(
+            index, useDefaultAccelerator_, &accelerator)) {
       const ui::PlatformAcceleratorCocoa* platformAccelerator =
           static_cast<const ui::PlatformAcceleratorCocoa*>(
               accelerator.platform_accelerator());
@@ -206,8 +202,8 @@ Role kRolesMap[] = {
     return NO;
 
   NSInteger modelIndex = [item tag];
-  ui::MenuModel* model =
-      static_cast<ui::MenuModel*>(
+  atom::AtomMenuModel* model =
+      static_cast<atom::AtomMenuModel*>(
           [[(id)item representedObject] pointerValue]);
   DCHECK(model);
   if (model) {
@@ -234,8 +230,8 @@ Role kRolesMap[] = {
 // item chosen.
 - (void)itemSelected:(id)sender {
   NSInteger modelIndex = [sender tag];
-  ui::MenuModel* model =
-      static_cast<ui::MenuModel*>(
+  atom::AtomMenuModel* model =
+      static_cast<atom::AtomMenuModel*>(
           [[sender representedObject] pointerValue]);
   DCHECK(model);
   if (model) {

+ 5 - 4
atom/browser/ui/file_dialog.h

@@ -23,10 +23,11 @@ typedef std::pair<std::string, std::vector<std::string> > Filter;
 typedef std::vector<Filter> Filters;
 
 enum FileDialogProperty {
-  FILE_DIALOG_OPEN_FILE        = 1 << 0,
-  FILE_DIALOG_OPEN_DIRECTORY   = 1 << 1,
-  FILE_DIALOG_MULTI_SELECTIONS = 1 << 2,
-  FILE_DIALOG_CREATE_DIRECTORY = 1 << 3,
+  FILE_DIALOG_OPEN_FILE         = 1 << 0,
+  FILE_DIALOG_OPEN_DIRECTORY    = 1 << 1,
+  FILE_DIALOG_MULTI_SELECTIONS  = 1 << 2,
+  FILE_DIALOG_CREATE_DIRECTORY  = 1 << 3,
+  FILE_DIALOG_SHOW_HIDDEN_FILES = 1 << 4,
 };
 
 typedef base::Callback<void(

+ 12 - 10
atom/browser/ui/file_dialog_gtk.cc

@@ -5,6 +5,7 @@
 #include "atom/browser/ui/file_dialog.h"
 
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "base/callback.h"
 #include "base/files/file_util.h"
 #include "base/strings/string_util.h"
@@ -41,7 +42,6 @@ class FileChooserDialog {
                     const base::FilePath& default_path,
                     const Filters& filters)
       : parent_(static_cast<atom::NativeWindowViews*>(parent_window)),
-        dialog_scope_(parent_window),
         filters_(filters) {
     const char* confirm_text = GTK_STOCK_OK;
 
@@ -87,12 +87,19 @@ class FileChooserDialog {
       AddFilters(filters);
   }
 
-  virtual ~FileChooserDialog() {
+  ~FileChooserDialog() {
     gtk_widget_destroy(dialog_);
     if (parent_)
       parent_->SetEnabled(true);
   }
 
+  void SetupProperties(int properties) {
+    if (properties & FILE_DIALOG_MULTI_SELECTIONS)
+      gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog()), TRUE);
+    if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES)
+      g_object_set(dialog(), "show-hidden", TRUE, NULL);
+  }
+
   void RunAsynchronous() {
     g_signal_connect(dialog_, "delete-event",
                      G_CALLBACK(gtk_widget_hide_on_delete), NULL);
@@ -146,7 +153,7 @@ class FileChooserDialog {
   base::FilePath AddExtensionForFilename(const gchar* filename) const;
 
   atom::NativeWindowViews* parent_;
-  atom::NativeWindow::DialogScope dialog_scope_;
+  atom::UnresponsiveSuppressor unresponsive_suppressor_;
 
   GtkWidget* dialog_;
 
@@ -235,9 +242,7 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
   FileChooserDialog open_dialog(action, parent_window, title, button_label,
                                 default_path, filters);
-  if (properties & FILE_DIALOG_MULTI_SELECTIONS)
-    gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(open_dialog.dialog()),
-                                         TRUE);
+  open_dialog.SetupProperties(properties);
 
   gtk_widget_show_all(open_dialog.dialog());
   int response = gtk_dialog_run(GTK_DIALOG(open_dialog.dialog()));
@@ -261,10 +266,7 @@ void ShowOpenDialog(atom::NativeWindow* parent_window,
     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
   FileChooserDialog* open_dialog = new FileChooserDialog(
       action, parent_window, title, button_label, default_path, filters);
-  if (properties & FILE_DIALOG_MULTI_SELECTIONS)
-    gtk_file_chooser_set_select_multiple(
-        GTK_FILE_CHOOSER(open_dialog->dialog()), TRUE);
-
+  open_dialog->SetupProperties(properties);
   open_dialog->RunOpenAsynchronous(callback);
 }
 

+ 2 - 0
atom/browser/ui/file_dialog_mac.mm

@@ -86,6 +86,8 @@ void SetupDialogForProperties(NSOpenPanel* dialog, int properties) {
     [dialog setCanCreateDirectories:YES];
   if (properties & FILE_DIALOG_MULTI_SELECTIONS)
     [dialog setAllowsMultipleSelection:YES];
+  if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES)
+    [dialog setShowsHiddenFiles:YES];
 }
 
 // Run modal dialog with parent window and return user's choice.

+ 4 - 1
atom/browser/ui/file_dialog_win.cc

@@ -10,6 +10,7 @@
 #include <shlobj.h>
 
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "base/files/file_util.h"
 #include "base/i18n/case_conversion.h"
 #include "base/strings/string_util.h"
@@ -108,7 +109,7 @@ class FileDialog {
   }
 
   bool Show(atom::NativeWindow* parent_window) {
-    atom::NativeWindow::DialogScope dialog_scope(parent_window);
+    atom::UnresponsiveSuppressor suppressor;
     HWND window = parent_window ? static_cast<atom::NativeWindowViews*>(
         parent_window)->GetAcceleratedWidget() :
         NULL;
@@ -201,6 +202,8 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
     options |= FOS_PICKFOLDERS;
   if (properties & FILE_DIALOG_MULTI_SELECTIONS)
     options |= FOS_ALLOWMULTISELECT;
+  if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES)
+    options |= FOS_FORCESHOWHIDDEN;
 
   FileDialog<CShellFileOpenDialog> open_dialog(
       default_path, title, button_label, filters, options);

+ 3 - 3
atom/browser/ui/message_box_gtk.cc

@@ -6,6 +6,7 @@
 
 #include "atom/browser/browser.h"
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "base/callback.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -35,8 +36,7 @@ class GtkMessageBox {
                 const std::string& message,
                 const std::string& detail,
                 const gfx::ImageSkia& icon)
-      : dialog_scope_(parent_window),
-        cancel_id_(cancel_id),
+      : cancel_id_(cancel_id),
         parent_(static_cast<NativeWindowViews*>(parent_window)) {
     // Create dialog.
     dialog_ = gtk_message_dialog_new(
@@ -147,7 +147,7 @@ class GtkMessageBox {
   CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnResponseDialog, int);
 
  private:
-  atom::NativeWindow::DialogScope dialog_scope_;
+  atom::UnresponsiveSuppressor unresponsive_suppressor_;
 
   // The id to return when the dialog is closed without pressing buttons.
   int cancel_id_;

+ 3 - 1
atom/browser/ui/message_box_win.cc

@@ -12,6 +12,7 @@
 
 #include "atom/browser/browser.h"
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/unresponsive_suppressor.h"
 #include "base/callback.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -198,7 +199,7 @@ int ShowMessageBox(NativeWindow* parent,
       static_cast<atom::NativeWindowViews*>(parent)->GetAcceleratedWidget() :
       NULL;
 
-  NativeWindow::DialogScope dialog_scope(parent);
+  atom::UnresponsiveSuppressor suppressor;
   return ShowMessageBoxUTF16(hwnd_parent,
                              type,
                              utf16_buttons,
@@ -239,6 +240,7 @@ void ShowMessageBox(NativeWindow* parent,
 }
 
 void ShowErrorBox(const base::string16& title, const base::string16& content) {
+  atom::UnresponsiveSuppressor suppressor;
   ShowMessageBoxUTF16(NULL, MESSAGE_BOX_TYPE_ERROR, {}, -1, 0, 0, L"Error",
                       title, content, gfx::ImageSkia());
 }

+ 5 - 1
atom/browser/ui/tray_icon.cc

@@ -27,7 +27,7 @@ void TrayIcon::DisplayBalloon(ImageType icon,
 }
 
 void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
-                                ui::SimpleMenuModel* menu_model) {
+                                AtomMenuModel* menu_model) {
 }
 
 gfx::Rect TrayIcon::GetBounds() {
@@ -68,6 +68,10 @@ void TrayIcon::NotifyDropFiles(const std::vector<std::string>& files) {
   FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files));
 }
 
+void TrayIcon::NotifyDropText(const std::string& text) {
+  FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropText(text));
+}
+
 void TrayIcon::NotifyDragEntered() {
   FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDragEntered());
 }

+ 4 - 3
atom/browser/ui/tray_icon.h

@@ -8,9 +8,9 @@
 #include <string>
 #include <vector>
 
+#include "atom/browser/ui/atom_menu_model.h"
 #include "atom/browser/ui/tray_icon_observer.h"
 #include "base/observer_list.h"
-#include "ui/base/models/simple_menu_model.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace atom {
@@ -55,10 +55,10 @@ class TrayIcon {
 
   // Popups the menu.
   virtual void PopUpContextMenu(const gfx::Point& pos,
-                                ui::SimpleMenuModel* menu_model);
+                                AtomMenuModel* menu_model);
 
   // Set the context menu for this icon.
-  virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
+  virtual void SetContextMenu(AtomMenuModel* menu_model) = 0;
 
   // Returns the bounds of tray icon.
   virtual gfx::Rect GetBounds();
@@ -75,6 +75,7 @@ class TrayIcon {
                           int modifiers = 0);
   void NotifyDrop();
   void NotifyDropFiles(const std::vector<std::string>& files);
+  void NotifyDropText(const std::string& text);
   void NotifyDragEntered();
   void NotifyDragExited();
   void NotifyDragEnded();

+ 2 - 3
atom/browser/ui/tray_icon_cocoa.h

@@ -9,7 +9,6 @@
 
 #include <string>
 
-#include "atom/browser/ui/atom_menu_model.h"
 #include "atom/browser/ui/tray_icon.h"
 #include "base/mac/scoped_nsobject.h"
 
@@ -30,8 +29,8 @@ class TrayIconCocoa : public TrayIcon,
   void SetTitle(const std::string& title) override;
   void SetHighlightMode(bool highlight) override;
   void PopUpContextMenu(const gfx::Point& pos,
-                        ui::SimpleMenuModel* menu_model) override;
-  void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
+                        AtomMenuModel* menu_model) override;
+  void SetContextMenu(AtomMenuModel* menu_model) override;
   gfx::Rect GetBounds() override;
 
  protected:

+ 17 - 7
atom/browser/ui/tray_icon_cocoa.mm

@@ -44,7 +44,10 @@ const CGFloat kVerticalTitleMargin = 2;
   inMouseEventSequence_ = NO;
 
   if ((self = [super initWithFrame: CGRectZero])) {
-    [self registerForDraggedTypes: @[NSFilenamesPboardType]];
+    [self registerForDraggedTypes: @[
+      NSFilenamesPboardType,
+      NSStringPboardType,
+    ]];
 
     // Create the status item.
     NSStatusItem * item = [[NSStatusBar systemStatusBar]
@@ -249,11 +252,12 @@ const CGFloat kVerticalTitleMargin = 2;
   [self setNeedsDisplay:YES];
 }
 
-- (void)popUpContextMenu:(ui::SimpleMenuModel*)menu_model {
+- (void)popUpContextMenu:(atom::AtomMenuModel*)menu_model {
   // Show a custom menu.
   if (menu_model) {
     base::scoped_nsobject<AtomMenuController> menuController(
-        [[AtomMenuController alloc] initWithModel:menu_model]);
+        [[AtomMenuController alloc] initWithModel:menu_model
+                            useDefaultAccelerator:NO]);
     forceHighlight_ = YES;  // Should highlight when showing menu.
     [self setNeedsDisplay:YES];
     [statusItem_ popUpStatusItemMenu:[menuController menu]];
@@ -306,7 +310,12 @@ const CGFloat kVerticalTitleMargin = 2;
       dropFiles.push_back(base::SysNSStringToUTF8(file));
     trayIcon_->NotifyDropFiles(dropFiles);
     return YES;
+  } else if ([[pboard types] containsObject:NSStringPboardType]) {
+    NSString* dropText = [pboard stringForType:NSStringPboardType];
+    trayIcon_->NotifyDropText(base::SysNSStringToUTF8(dropText));
+    return YES;
   }
+
   return NO;
 }
 
@@ -365,18 +374,19 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) {
 }
 
 void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos,
-                                     ui::SimpleMenuModel* menu_model) {
+                                     AtomMenuModel* menu_model) {
   [status_item_view_ popUpContextMenu:menu_model];
 }
 
-void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) {
+void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) {
   // Substribe to MenuClosed event.
   if (menu_model_)
     menu_model_->RemoveObserver(this);
-  static_cast<AtomMenuModel*>(menu_model)->AddObserver(this);
+  menu_model->AddObserver(this);
 
   // Create native menu.
-  menu_.reset([[AtomMenuController alloc] initWithModel:menu_model]);
+  menu_.reset([[AtomMenuController alloc] initWithModel:menu_model
+                                  useDefaultAccelerator:NO]);
   [status_item_view_ setMenuController:menu_.get()];
 }
 

+ 1 - 1
atom/browser/ui/tray_icon_gtk.cc

@@ -50,7 +50,7 @@ void TrayIconGtk::SetToolTip(const std::string& tool_tip) {
   icon_->SetToolTip(base::UTF8ToUTF16(tool_tip));
 }
 
-void TrayIconGtk::SetContextMenu(ui::SimpleMenuModel* menu_model) {
+void TrayIconGtk::SetContextMenu(AtomMenuModel* menu_model) {
   icon_->UpdatePlatformContextMenu(menu_model);
 }
 

+ 1 - 1
atom/browser/ui/tray_icon_gtk.h

@@ -25,7 +25,7 @@ class TrayIconGtk : public TrayIcon,
   // TrayIcon:
   void SetImage(const gfx::Image& image) override;
   void SetToolTip(const std::string& tool_tip) override;
-  void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
+  void SetContextMenu(AtomMenuModel* menu_model) override;
 
  private:
   // views::StatusIconLinux::Delegate:

+ 1 - 0
atom/browser/ui/tray_icon_observer.h

@@ -24,6 +24,7 @@ class TrayIconObserver {
   virtual void OnRightClicked(const gfx::Rect& bounds, int modifiers) {}
   virtual void OnDrop() {}
   virtual void OnDropFiles(const std::vector<std::string>& files) {}
+  virtual void OnDropText(const std::string& text) {}
   virtual void OnDragEntered() {}
   virtual void OnDragExited() {}
   virtual void OnDragEnded() {}

+ 14 - 14
atom/browser/ui/views/global_menu_bar_x11.cc

@@ -16,6 +16,7 @@
 #include <glib-object.h>
 
 #include "atom/browser/native_window_views.h"
+#include "atom/browser/ui/atom_menu_model.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -23,7 +24,6 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
-#include "ui/base/models/menu_model.h"
 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
 
 // libdbusmenu-glib types
@@ -141,8 +141,8 @@ void EnsureMethodsLoaded() {
       dlsym(dbusmenu_lib, "dbusmenu_server_set_root"));
 }
 
-ui::MenuModel* ModelForMenuItem(DbusmenuMenuitem* item) {
-  return reinterpret_cast<ui::MenuModel*>(
+AtomMenuModel* ModelForMenuItem(DbusmenuMenuitem* item) {
+  return reinterpret_cast<AtomMenuModel*>(
       g_object_get_data(G_OBJECT(item), "model"));
 }
 
@@ -188,7 +188,7 @@ std::string GlobalMenuBarX11::GetPathForWindow(gfx::AcceleratedWidget xid) {
   return base::StringPrintf("/com/canonical/menu/%lX", xid);
 }
 
-void GlobalMenuBarX11::SetMenu(ui::MenuModel* menu_model) {
+void GlobalMenuBarX11::SetMenu(AtomMenuModel* menu_model) {
   if (!IsServerStarted())
     return;
 
@@ -218,14 +218,14 @@ void GlobalMenuBarX11::OnWindowUnmapped() {
   GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_);
 }
 
-void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model,
+void GlobalMenuBarX11::BuildMenuFromModel(AtomMenuModel* model,
                                           DbusmenuMenuitem* parent) {
   for (int i = 0; i < model->GetItemCount(); ++i) {
     DbusmenuMenuitem* item = menuitem_new();
     menuitem_property_set_bool(item, kPropertyVisible, model->IsVisibleAt(i));
 
-    ui::MenuModel::ItemType type = model->GetTypeAt(i);
-    if (type == ui::MenuModel::TYPE_SEPARATOR) {
+    AtomMenuModel::ItemType type = model->GetTypeAt(i);
+    if (type == AtomMenuModel::TYPE_SEPARATOR) {
       menuitem_property_set(item, kPropertyType, kTypeSeparator);
     } else {
       std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
@@ -236,22 +236,22 @@ void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model,
       g_object_set_data(G_OBJECT(item), "model", model);
       SetMenuItemID(item, i);
 
-      if (type == ui::MenuModel::TYPE_SUBMENU) {
+      if (type == AtomMenuModel::TYPE_SUBMENU) {
         menuitem_property_set(item, kPropertyChildrenDisplay, kDisplaySubmenu);
         g_signal_connect(item, "about-to-show",
                          G_CALLBACK(OnSubMenuShowThunk), this);
       } else {
         ui::Accelerator accelerator;
-        if (model->GetAcceleratorAt(i, &accelerator))
+        if (model->GetAcceleratorAtWithParams(i, true, &accelerator))
           RegisterAccelerator(item, accelerator);
 
         g_signal_connect(item, "item-activated",
                          G_CALLBACK(OnItemActivatedThunk), this);
 
-        if (type == ui::MenuModel::TYPE_CHECK ||
-            type == ui::MenuModel::TYPE_RADIO) {
+        if (type == AtomMenuModel::TYPE_CHECK ||
+            type == AtomMenuModel::TYPE_RADIO) {
           menuitem_property_set(item, kPropertyToggleType,
-              type == ui::MenuModel::TYPE_CHECK ? kToggleCheck : kToggleRadio);
+              type == AtomMenuModel::TYPE_CHECK ? kToggleCheck : kToggleRadio);
           menuitem_property_set_int(item, kPropertyToggleState,
               model->IsItemCheckedAt(i));
         }
@@ -296,14 +296,14 @@ void GlobalMenuBarX11::RegisterAccelerator(DbusmenuMenuitem* item,
 void GlobalMenuBarX11::OnItemActivated(DbusmenuMenuitem* item,
                                        unsigned int timestamp) {
   int id;
-  ui::MenuModel* model = ModelForMenuItem(item);
+  AtomMenuModel* model = ModelForMenuItem(item);
   if (model && GetMenuItemID(item, &id))
     model->ActivatedAt(id, 0);
 }
 
 void GlobalMenuBarX11::OnSubMenuShow(DbusmenuMenuitem* item) {
   int id;
-  ui::MenuModel* model = ModelForMenuItem(item);
+  AtomMenuModel* model = ModelForMenuItem(item);
   if (!model || !GetMenuItemID(item, &id))
     return;
 

+ 3 - 3
atom/browser/ui/views/global_menu_bar_x11.h

@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "atom/browser/ui/atom_menu_model.h"
 #include "base/macros.h"
 #include "base/compiler_specific.h"
 #include "ui/base/glib/glib_signal.h"
@@ -17,7 +18,6 @@ typedef struct _DbusmenuServer   DbusmenuServer;
 
 namespace ui {
 class Accelerator;
-class MenuModel;
 }
 
 namespace atom {
@@ -43,7 +43,7 @@ class GlobalMenuBarX11 {
   // Creates the object path for DbusmenuServer which is attached to |xid|.
   static std::string GetPathForWindow(gfx::AcceleratedWidget xid);
 
-  void SetMenu(ui::MenuModel* menu_model);
+  void SetMenu(AtomMenuModel* menu_model);
   bool IsServerStarted() const;
 
   // Called by NativeWindow when it show/hides.
@@ -55,7 +55,7 @@ class GlobalMenuBarX11 {
   void InitServer(gfx::AcceleratedWidget xid);
 
   // Create a menu from menu model.
-  void BuildMenuFromModel(ui::MenuModel* model, DbusmenuMenuitem* parent);
+  void BuildMenuFromModel(AtomMenuModel* model, DbusmenuMenuitem* parent);
 
   // Sets the accelerator for |item|.
   void RegisterAccelerator(DbusmenuMenuitem* item,

+ 5 - 5
atom/browser/ui/views/menu_bar.cc

@@ -58,7 +58,7 @@ MenuBar::MenuBar()
 MenuBar::~MenuBar() {
 }
 
-void MenuBar::SetMenu(ui::MenuModel* model) {
+void MenuBar::SetMenu(AtomMenuModel* model) {
   menu_model_ = model;
   RemoveAllChildViews(true);
 
@@ -105,7 +105,7 @@ int MenuBar::GetItemCount() const {
 }
 
 bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& point,
-                                           ui::MenuModel** menu_model,
+                                           AtomMenuModel** menu_model,
                                            views::MenuButton** button) {
   gfx::Point location(point);
   views::View::ConvertPointFromScreen(this, &location);
@@ -117,7 +117,7 @@ bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& point,
   for (int i = 0; i < child_count(); ++i) {
     views::View* view = child_at(i);
     if (view->bounds().Contains(location) &&
-        (menu_model_->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU)) {
+        (menu_model_->GetTypeAt(i) == AtomMenuModel::TYPE_SUBMENU)) {
       *menu_model = menu_model_->GetSubmenuModelAt(i);
       *button = static_cast<views::MenuButton*>(view);
       return true;
@@ -144,8 +144,8 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
     return;
 
   int id = source->tag();
-  ui::MenuModel::ItemType type = menu_model_->GetTypeAt(id);
-  if (type != ui::MenuModel::TYPE_SUBMENU) {
+  AtomMenuModel::ItemType type = menu_model_->GetTypeAt(id);
+  if (type != AtomMenuModel::TYPE_SUBMENU) {
     menu_model_->ActivatedAt(id, 0);
     return;
   }

+ 4 - 7
atom/browser/ui/views/menu_bar.h

@@ -5,14 +5,11 @@
 #ifndef ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
 #define ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
 
+#include "atom/browser/ui/atom_menu_model.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/view.h"
 
-namespace ui {
-class MenuModel;
-}
-
 namespace views {
 class MenuButton;
 }
@@ -29,7 +26,7 @@ class MenuBar : public views::View,
   virtual ~MenuBar();
 
   // Replaces current menu with a new one.
-  void SetMenu(ui::MenuModel* menu_model);
+  void SetMenu(AtomMenuModel* menu_model);
 
   // Shows underline under accelerators.
   void SetAcceleratorVisibility(bool visible);
@@ -46,7 +43,7 @@ class MenuBar : public views::View,
 
   // Get the menu under specified screen point.
   bool GetMenuButtonFromScreenPoint(const gfx::Point& point,
-                                    ui::MenuModel** menu_model,
+                                    AtomMenuModel** menu_model,
                                     views::MenuButton** button);
 
  protected:
@@ -74,7 +71,7 @@ class MenuBar : public views::View,
   SkColor hover_color_;
 #endif
 
-  ui::MenuModel* menu_model_;
+  AtomMenuModel* menu_model_;
 
   DISALLOW_COPY_AND_ASSIGN(MenuBar);
 };

+ 5 - 5
atom/browser/ui/views/menu_delegate.cc

@@ -5,10 +5,10 @@
 #include "atom/browser/ui/views/menu_delegate.h"
 
 #include "atom/browser/ui/views/menu_bar.h"
+#include "atom/browser/ui/views/menu_model_adapter.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_model_adapter.h"
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/widget/widget.h"
 
@@ -22,7 +22,7 @@ MenuDelegate::MenuDelegate(MenuBar* menu_bar)
 MenuDelegate::~MenuDelegate() {
 }
 
-void MenuDelegate::RunMenu(ui::MenuModel* model, views::MenuButton* button) {
+void MenuDelegate::RunMenu(AtomMenuModel* model, views::MenuButton* button) {
   gfx::Point screen_loc;
   views::View::ConvertPointToScreen(button, &screen_loc);
   // Subtract 1 from the height to make the popup flush with the button border.
@@ -30,10 +30,10 @@ void MenuDelegate::RunMenu(ui::MenuModel* model, views::MenuButton* button) {
                    button->height() - 1);
 
   id_ = button->tag();
-  adapter_.reset(new views::MenuModelAdapter(model));
+  adapter_.reset(new MenuModelAdapter(model));
 
   views::MenuItemView* item = new views::MenuItemView(this);
-  static_cast<views::MenuModelAdapter*>(adapter_.get())->BuildMenu(item);
+  static_cast<MenuModelAdapter*>(adapter_.get())->BuildMenu(item);
 
   menu_runner_.reset(new views::MenuRunner(
       item,
@@ -102,7 +102,7 @@ views::MenuItemView* MenuDelegate::GetSiblingMenu(
     bool* has_mnemonics,
     views::MenuButton**) {
   views::MenuButton* button;
-  ui::MenuModel* model;
+  AtomMenuModel* model;
   if (menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, &button) &&
       button->tag() != id_) {
     DCHECK(menu_runner_->IsRunning());

+ 2 - 5
atom/browser/ui/views/menu_delegate.h

@@ -7,16 +7,13 @@
 
 #include <memory>
 
+#include "atom/browser/ui/atom_menu_model.h"
 #include "ui/views/controls/menu/menu_delegate.h"
 
 namespace views {
 class MenuRunner;
 }
 
-namespace ui {
-class MenuModel;
-}
-
 namespace atom {
 
 class MenuBar;
@@ -26,7 +23,7 @@ class MenuDelegate : public views::MenuDelegate {
   explicit MenuDelegate(MenuBar* menu_bar);
   virtual ~MenuDelegate();
 
-  void RunMenu(ui::MenuModel* model, views::MenuButton* button);
+  void RunMenu(AtomMenuModel* model, views::MenuButton* button);
 
  protected:
   // views::MenuDelegate:

+ 28 - 0
atom/browser/ui/views/menu_model_adapter.cc

@@ -0,0 +1,28 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/ui/views/menu_model_adapter.h"
+
+namespace atom {
+
+MenuModelAdapter::MenuModelAdapter(AtomMenuModel* menu_model)
+  : views::MenuModelAdapter(menu_model),
+    menu_model_(menu_model) {
+}
+
+MenuModelAdapter::~MenuModelAdapter() {
+}
+
+bool MenuModelAdapter::GetAccelerator(int id,
+                                      ui::Accelerator* accelerator) const {
+  ui::MenuModel* model = menu_model_;
+  int index = 0;
+  if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) {
+    return static_cast<AtomMenuModel*>(model)->
+      GetAcceleratorAtWithParams(index, true, accelerator);
+  }
+  return false;
+}
+
+}  // namespace atom

+ 29 - 0
atom/browser/ui/views/menu_model_adapter.h

@@ -0,0 +1,29 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_UI_VIEWS_MENU_MODEL_ADAPTER_H_
+#define ATOM_BROWSER_UI_VIEWS_MENU_MODEL_ADAPTER_H_
+
+#include "atom/browser/ui/atom_menu_model.h"
+#include "ui/views/controls/menu/menu_model_adapter.h"
+
+namespace atom {
+
+class MenuModelAdapter : public views::MenuModelAdapter {
+ public:
+  explicit MenuModelAdapter(AtomMenuModel* menu_model);
+  virtual ~MenuModelAdapter();
+
+ protected:
+  bool GetAccelerator(int id, ui::Accelerator* accelerator) const override;
+
+ private:
+  AtomMenuModel* menu_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(MenuModelAdapter);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_UI_VIEWS_MENU_MODEL_ADAPTER_H_

+ 2 - 2
atom/browser/ui/win/notify_icon.cc

@@ -132,7 +132,7 @@ void NotifyIcon::DisplayBalloon(HICON icon,
 }
 
 void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
-                                  ui::SimpleMenuModel* menu_model) {
+                                  AtomMenuModel* menu_model) {
   // Returns if context menu isn't set.
   if (menu_model == nullptr && menu_model_ == nullptr)
     return;
@@ -154,7 +154,7 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
       NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE));
 }
 
-void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {
+void NotifyIcon::SetContextMenu(AtomMenuModel* menu_model) {
   menu_model_ = menu_model;
 }
 

+ 3 - 3
atom/browser/ui/win/notify_icon.h

@@ -51,8 +51,8 @@ class NotifyIcon : public TrayIcon {
                       const base::string16& title,
                       const base::string16& contents) override;
   void PopUpContextMenu(const gfx::Point& pos,
-                        ui::SimpleMenuModel* menu_model) override;
-  void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
+                        AtomMenuModel* menu_model) override;
+  void SetContextMenu(AtomMenuModel* menu_model) override;
   gfx::Rect GetBounds() override;
 
  private:
@@ -74,7 +74,7 @@ class NotifyIcon : public TrayIcon {
   base::win::ScopedHICON icon_;
 
   // The context menu.
-  ui::SimpleMenuModel* menu_model_;
+  AtomMenuModel* menu_model_;
 
   DISALLOW_COPY_AND_ASSIGN(NotifyIcon);
 };

+ 16 - 0
atom/browser/ui/win/taskbar_host.cc

@@ -142,6 +142,22 @@ bool TaskbarHost::SetOverlayIcon(
       window, icon.get(), base::UTF8ToUTF16(text).c_str()));
 }
 
+bool TaskbarHost::SetThumbnailClip(HWND window, const gfx::Rect& region) {
+  if (!InitializeTaskbar())
+    return false;
+
+  if (region.IsEmpty()) {
+    return SUCCEEDED(taskbar_->SetThumbnailClip(window, NULL));
+  } else {
+    RECT rect;
+    rect.left = region.x();
+    rect.right = region.right();
+    rect.top = region.y();
+    rect.bottom = region.bottom();
+    return SUCCEEDED(taskbar_->SetThumbnailClip(window, &rect));
+  }
+}
+
 bool TaskbarHost::HandleThumbarButtonEvent(int button_id) {
   if (ContainsKey(callback_map_, button_id)) {
     auto callback = callback_map_[button_id];

+ 4 - 0
atom/browser/ui/win/taskbar_host.h

@@ -13,6 +13,7 @@
 
 #include "base/callback.h"
 #include "base/win/scoped_comptr.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image.h"
 
 namespace atom {
@@ -40,6 +41,9 @@ class TaskbarHost {
   bool SetOverlayIcon(
       HWND window, const gfx::Image& overlay, const std::string& text);
 
+  // Set the region of the window to show as a thumbnail in taskbar.
+  bool TaskbarHost::SetThumbnailClip(HWND window, const gfx::Rect& region);
+
   // Called by the window that there is a button in thumbar clicked.
   bool HandleThumbarButtonEvent(int button_id);
 

+ 27 - 0
atom/browser/unresponsive_suppressor.cc

@@ -0,0 +1,27 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/unresponsive_suppressor.h"
+
+namespace atom {
+
+namespace {
+
+int g_suppress_level = 0;
+
+}  // namespace
+
+bool IsUnresponsiveEventSuppressed() {
+  return g_suppress_level > 0;
+}
+
+UnresponsiveSuppressor::UnresponsiveSuppressor() {
+  g_suppress_level++;
+}
+
+UnresponsiveSuppressor::~UnresponsiveSuppressor() {
+  g_suppress_level--;
+}
+
+}  // namespace atom

+ 25 - 0
atom/browser/unresponsive_suppressor.h

@@ -0,0 +1,25 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_UNRESPONSIVE_SUPPRESSOR_H_
+#define ATOM_BROWSER_UNRESPONSIVE_SUPPRESSOR_H_
+
+#include "base/macros.h"
+
+namespace atom {
+
+bool IsUnresponsiveEventSuppressed();
+
+class UnresponsiveSuppressor {
+ public:
+  UnresponsiveSuppressor();
+  ~UnresponsiveSuppressor();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(UnresponsiveSuppressor);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_UNRESPONSIVE_SUPPRESSOR_H_

+ 8 - 4
atom/browser/web_view_guest_delegate.cc

@@ -7,6 +7,7 @@
 #include "atom/browser/api/atom_api_web_contents.h"
 #include "atom/common/native_mate_converters/gurl_converter.h"
 #include "content/public/browser/guest_host.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -95,10 +96,13 @@ void WebViewGuestDelegate::SetSize(const SetSizeParams& params) {
   auto_size_enabled_ = enable_auto_size;
 }
 
-void WebViewGuestDelegate::DidCommitProvisionalLoadForFrame(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& url, ui::PageTransition transition_type) {
-  api_web_contents_->Emit("load-commit", url, !render_frame_host->GetParent());
+void WebViewGuestDelegate::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) {
+    auto is_main_frame = navigation_handle->IsInMainFrame();
+    auto url = navigation_handle->GetURL();
+    api_web_contents_->Emit("load-commit", url, is_main_frame);
+  }
 }
 
 void WebViewGuestDelegate::DidAttach(int guest_proxy_routing_id) {

+ 2 - 3
atom/browser/web_view_guest_delegate.h

@@ -47,9 +47,8 @@ class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
 
  protected:
   // content::WebContentsObserver:
-  void DidCommitProvisionalLoadForFrame(
-      content::RenderFrameHost* render_frame_host,
-      const GURL& url, ui::PageTransition transition_type) override;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
 
   // content::BrowserPluginGuestDelegate:
   void DidAttach(int guest_proxy_routing_id) final;

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