diff --git a/app/atom_main_delegate.cc b/app/atom_main_delegate.cc index 40a42d721..d8f0c693d 100644 --- a/app/atom_main_delegate.cc +++ b/app/atom_main_delegate.cc @@ -51,6 +51,15 @@ void AtomMainDelegate::PreSandboxStartup() { InitializeResourceBundle(); CommandLine* command_line = CommandLine::ForCurrentProcess(); + std::string process_type = command_line->GetSwitchValueASCII( + switches::kProcessType); + + // Don't append arguments for renderer process. + if (process_type == switches::kRendererProcess) + return; + + // Add a flag to mark the start of switches added by atom-shell. + command_line->AppendSwitch("atom-shell-switches-start"); // Disable renderer sandbox for most of node's functions. command_line->AppendSwitch(switches::kNoSandbox); @@ -60,7 +69,7 @@ void AtomMainDelegate::PreSandboxStartup() { command_line->AppendSwitch(switches::kDisableAcceleratedCompositing); // Add a flag to mark the end of switches added by atom-shell. - command_line->AppendSwitch("no-more-switches"); + command_line->AppendSwitch("atom-shell-switches-end"); } void AtomMainDelegate::InitializeResourceBundle() { diff --git a/atom.gyp b/atom.gyp index 9cd9f2967..4ff70a69b 100644 --- a/atom.gyp +++ b/atom.gyp @@ -8,7 +8,7 @@ 'app/atom_main.h', ], 'bundle_sources': [ - 'browser/mac/atom.icns', + 'browser/resources/mac/atom.icns', ], 'coffee_sources': [ 'browser/api/lib/app.coffee', @@ -65,7 +65,6 @@ 'browser/api/atom_browser_bindings.h', 'browser/auto_updater.cc', 'browser/auto_updater.h', - 'browser/auto_updater_delegate.cc', 'browser/auto_updater_delegate.h', 'browser/auto_updater_linux.cc', 'browser/auto_updater_mac.mm', @@ -111,18 +110,18 @@ 'browser/ui/accelerator_util_gtk.cc', 'browser/ui/accelerator_util_mac.mm', 'browser/ui/accelerator_util_win.cc', - 'browser/ui/atom_event_processing_window.h', - 'browser/ui/atom_event_processing_window.mm', - 'browser/ui/atom_menu_controller_mac.h', - 'browser/ui/atom_menu_controller_mac.mm', + 'browser/ui/cocoa/atom_menu_controller.h', + 'browser/ui/cocoa/atom_menu_controller.mm', + 'browser/ui/cocoa/event_processing_window.h', + 'browser/ui/cocoa/event_processing_window.mm', + 'browser/ui/cocoa/nsalert_synchronous_sheet.h', + 'browser/ui/cocoa/nsalert_synchronous_sheet.mm', 'browser/ui/file_dialog.h', 'browser/ui/file_dialog_mac.mm', 'browser/ui/file_dialog_win.cc', 'browser/ui/message_box.h', 'browser/ui/message_box_mac.mm', 'browser/ui/message_box_win.cc', - 'browser/ui/nsalert_synchronous_sheet_mac.h', - 'browser/ui/nsalert_synchronous_sheet_mac.mm', 'browser/ui/gtk/gtk_window_util.cc', 'browser/ui/gtk/gtk_window_util.h', 'browser/ui/win/menu_2.cc', @@ -202,20 +201,13 @@ 'conditions': [ ['OS=="win"', { 'app_sources': [ - 'app/win/resource.h', - 'app/win/atom.ico', - 'app/win/atom.rc', + 'browser/resources/win/resource.h', + 'browser/resources/win/atom.ico', + 'browser/resources/win/atom.rc', '<(libchromiumcontent_src_dir)/content/app/startup_helper_win.cc', ], }], # OS=="win" ], - 'fix_framework_link_command': [ - 'install_name_tool', - '-change', - '@loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle', - '@rpath/Sparkle.framework/Versions/A/Sparkle', - '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' - ], 'atom_source_root': '& args) { // static void App::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - v8::Local t = v8::FunctionTemplate::New(New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("Application")); diff --git a/browser/api/atom_api_auto_updater.cc b/browser/api/atom_api_auto_updater.cc index bfb55252e..69ed10089 100644 --- a/browser/api/atom_api_auto_updater.cc +++ b/browser/api/atom_api_auto_updater.cc @@ -4,6 +4,7 @@ #include "browser/api/atom_api_auto_updater.h" +#include "base/time/time.h" #include "base/values.h" #include "browser/auto_updater.h" #include "common/v8/native_type_conversions.h" @@ -17,38 +18,47 @@ namespace api { AutoUpdater::AutoUpdater(v8::Handle wrapper) : EventEmitter(wrapper) { auto_updater::AutoUpdater::SetDelegate(this); - auto_updater::AutoUpdater::Init(); } AutoUpdater::~AutoUpdater() { auto_updater::AutoUpdater::SetDelegate(NULL); } -void AutoUpdater::WillInstallUpdate(const std::string& version, - const base::Closure& install) { - continue_update_ = install; - +void AutoUpdater::OnError(const std::string& error) { base::ListValue args; - args.AppendString(version); - bool prevent_default = Emit("will-install-update-raw", &args); - - if (!prevent_default) - install.Run(); + args.AppendString(error); + Emit("error", &args); } -void AutoUpdater::ReadyForUpdateOnQuit(const std::string& version, - const base::Closure& quit_and_install) { +void AutoUpdater::OnCheckingForUpdate() { + Emit("checking-for-update"); +} + +void AutoUpdater::OnUpdateAvailable() { + Emit("update-available"); +} + +void AutoUpdater::OnUpdateNotAvailable() { + Emit("update-not-available"); +} + +void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes, + const std::string& release_name, + const base::Time& release_date, + const std::string& update_url, + const base::Closure& quit_and_install) { quit_and_install_ = quit_and_install; base::ListValue args; - args.AppendString(version); - Emit("ready-for-update-on-quit-raw", &args); + args.AppendString(release_notes); + args.AppendString(release_name); + args.AppendDouble(release_date.ToJsTime()); + args.AppendString(update_url); + Emit("update-downloaded-raw", &args); } // static void AutoUpdater::New(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - if (!args.IsConstructCall()) return node::ThrowError("Require constructor call"); @@ -60,39 +70,12 @@ void AutoUpdater::SetFeedURL(const v8::FunctionCallbackInfo& args) { auto_updater::AutoUpdater::SetFeedURL(FromV8Value(args[0])); } -// static -void AutoUpdater::SetAutomaticallyChecksForUpdates( - const v8::FunctionCallbackInfo& args) { - auto_updater::AutoUpdater::SetAutomaticallyChecksForUpdates( - FromV8Value(args[0])); -} - -// static -void AutoUpdater::SetAutomaticallyDownloadsUpdates( - const v8::FunctionCallbackInfo& args) { - auto_updater::AutoUpdater::SetAutomaticallyDownloadsUpdates( - FromV8Value(args[0])); -} - // static void AutoUpdater::CheckForUpdates( const v8::FunctionCallbackInfo& args) { auto_updater::AutoUpdater::CheckForUpdates(); } -// static -void AutoUpdater::CheckForUpdatesInBackground( - const v8::FunctionCallbackInfo& args) { - auto_updater::AutoUpdater::CheckForUpdatesInBackground(); -} - -// static -void AutoUpdater::ContinueUpdate( - const v8::FunctionCallbackInfo& args) { - AutoUpdater* self = AutoUpdater::Unwrap(args.This()); - self->continue_update_.Run(); -} - // static void AutoUpdater::QuitAndInstall( const v8::FunctionCallbackInfo& args) { @@ -102,26 +85,13 @@ void AutoUpdater::QuitAndInstall( // static void AutoUpdater::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - v8::Local t( v8::FunctionTemplate::New(AutoUpdater::New)); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("AutoUpdater")); NODE_SET_PROTOTYPE_METHOD(t, "setFeedUrl", SetFeedURL); - NODE_SET_PROTOTYPE_METHOD(t, - "setAutomaticallyChecksForUpdates", - SetAutomaticallyChecksForUpdates); - NODE_SET_PROTOTYPE_METHOD(t, - "setAutomaticallyDownloadsUpdates", - SetAutomaticallyDownloadsUpdates); NODE_SET_PROTOTYPE_METHOD(t, "checkForUpdates", CheckForUpdates); - NODE_SET_PROTOTYPE_METHOD(t, - "checkForUpdatesInBackground", - CheckForUpdatesInBackground); - - NODE_SET_PROTOTYPE_METHOD(t, "continueUpdate", ContinueUpdate); NODE_SET_PROTOTYPE_METHOD(t, "quitAndInstall", QuitAndInstall); target->Set(v8::String::NewSymbol("AutoUpdater"), t->GetFunction()); diff --git a/browser/api/atom_api_auto_updater.h b/browser/api/atom_api_auto_updater.h index 03d649e2b..0207cbe6a 100644 --- a/browser/api/atom_api_auto_updater.h +++ b/browser/api/atom_api_auto_updater.h @@ -24,28 +24,27 @@ class AutoUpdater : public EventEmitter, protected: explicit AutoUpdater(v8::Handle wrapper); - virtual void WillInstallUpdate(const std::string& version, - const base::Closure& install) OVERRIDE; - virtual void ReadyForUpdateOnQuit( - const std::string& version, + // AutoUpdaterDelegate implementations. + virtual void OnError(const std::string& error) OVERRIDE; + virtual void OnCheckingForUpdate() OVERRIDE; + virtual void OnUpdateAvailable() OVERRIDE; + virtual void OnUpdateNotAvailable() OVERRIDE; + virtual void OnUpdateDownloaded( + const std::string& release_notes, + const std::string& release_name, + const base::Time& release_date, + const std::string& update_url, const base::Closure& quit_and_install) OVERRIDE; private: static void New(const v8::FunctionCallbackInfo& args); static void SetFeedURL(const v8::FunctionCallbackInfo& args); - static void SetAutomaticallyChecksForUpdates( - const v8::FunctionCallbackInfo& args); - static void SetAutomaticallyDownloadsUpdates( - const v8::FunctionCallbackInfo& args); static void CheckForUpdates(const v8::FunctionCallbackInfo& args); - static void CheckForUpdatesInBackground( - const v8::FunctionCallbackInfo& args); static void ContinueUpdate(const v8::FunctionCallbackInfo& args); static void QuitAndInstall(const v8::FunctionCallbackInfo& args); - base::Closure continue_update_; base::Closure quit_and_install_; DISALLOW_COPY_AND_ASSIGN(AutoUpdater); diff --git a/browser/api/atom_api_dialog.cc b/browser/api/atom_api_dialog.cc index f42eb1b6e..2eb555ccd 100644 --- a/browser/api/atom_api_dialog.cc +++ b/browser/api/atom_api_dialog.cc @@ -19,7 +19,9 @@ namespace { template void CallV8Function(const RefCountedV8Function& callback, T arg) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); + v8::Handle value = ToV8Value(arg); callback->NewHandle(node_isolate)->Call( v8::Context::GetCurrent()->Global(), 1, &value); @@ -34,8 +36,6 @@ void CallV8Function2(const RefCountedV8Function& callback, bool result, T arg) { } void Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - NODE_SET_METHOD(target, "showMessageBox", ShowMessageBox); NODE_SET_METHOD(target, "showOpenDialog", ShowOpenDialog); NODE_SET_METHOD(target, "showSaveDialog", ShowSaveDialog); diff --git a/browser/api/atom_api_menu.cc b/browser/api/atom_api_menu.cc index ffc9c5a26..cc3a514d5 100644 --- a/browser/api/atom_api_menu.cc +++ b/browser/api/atom_api_menu.cc @@ -24,6 +24,7 @@ v8::Handle CallDelegate(v8::Handle default_value, v8::Handle menu, const char* method, int command_id) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); v8::Handle delegate = menu->Get(v8::String::New("delegate")); @@ -52,6 +53,7 @@ Menu::~Menu() { } bool Menu::IsCommandIdChecked(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return CallDelegate(v8::False(), const_cast(this)->handle(), @@ -60,6 +62,7 @@ bool Menu::IsCommandIdChecked(int command_id) const { } bool Menu::IsCommandIdEnabled(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return CallDelegate(v8::True(), const_cast(this)->handle(), @@ -68,6 +71,7 @@ bool Menu::IsCommandIdEnabled(int command_id) const { } bool Menu::IsCommandIdVisible(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return CallDelegate(v8::True(), const_cast(this)->handle(), @@ -77,6 +81,7 @@ bool Menu::IsCommandIdVisible(int command_id) const { bool Menu::GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); v8::Handle shortcut = CallDelegate(v8::Undefined(), handle(), @@ -91,6 +96,7 @@ bool Menu::GetAcceleratorForCommandId(int command_id, } bool Menu::IsItemForCommandIdDynamic(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return CallDelegate(v8::False(), const_cast(this)->handle(), @@ -99,6 +105,7 @@ bool Menu::IsItemForCommandIdDynamic(int command_id) const { } string16 Menu::GetLabelForCommandId(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return FromV8Value(CallDelegate(v8::False(), const_cast(this)->handle(), @@ -107,6 +114,7 @@ string16 Menu::GetLabelForCommandId(int command_id) const { } string16 Menu::GetSublabelForCommandId(int command_id) const { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); return FromV8Value(CallDelegate(v8::False(), const_cast(this)->handle(), @@ -115,14 +123,13 @@ string16 Menu::GetSublabelForCommandId(int command_id) const { } void Menu::ExecuteCommand(int command_id, int event_flags) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); CallDelegate(v8::False(), handle(), "executeCommand", command_id); } // static void Menu::New(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - if (!args.IsConstructCall()) return node::ThrowError("Require constructor call"); @@ -307,8 +314,6 @@ void Menu::Popup(const v8::FunctionCallbackInfo& args) { // static void Menu::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - v8::Local t(v8::FunctionTemplate::New(Menu::New)); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("Menu")); diff --git a/browser/api/atom_api_menu_mac.h b/browser/api/atom_api_menu_mac.h index 46c133e66..62da458ae 100644 --- a/browser/api/atom_api_menu_mac.h +++ b/browser/api/atom_api_menu_mac.h @@ -7,7 +7,7 @@ #include "browser/api/atom_api_menu.h" -#import "browser/ui/atom_menu_controller_mac.h" +#import "browser/ui/cocoa/atom_menu_controller.h" namespace atom { diff --git a/browser/api/atom_api_menu_mac.mm b/browser/api/atom_api_menu_mac.mm index 432ddb52e..12e271060 100644 --- a/browser/api/atom_api_menu_mac.mm +++ b/browser/api/atom_api_menu_mac.mm @@ -74,8 +74,6 @@ void MenuMac::SendActionToFirstResponder(const std::string& action) { // static void Menu::SetApplicationMenu(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - if (!args[0]->IsObject()) return node::ThrowTypeError("Bad argument"); @@ -94,8 +92,6 @@ void Menu::SetApplicationMenu(const v8::FunctionCallbackInfo& args) { // static void Menu::SendActionToFirstResponder( const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - std::string action; if (!FromV8Arguments(args, &action)) return node::ThrowTypeError("Bad argument"); diff --git a/browser/api/atom_api_menu_win.cc b/browser/api/atom_api_menu_win.cc index c5f552236..e645478ac 100644 --- a/browser/api/atom_api_menu_win.cc +++ b/browser/api/atom_api_menu_win.cc @@ -31,8 +31,6 @@ void MenuWin::Popup(NativeWindow* native_window) { // static void Menu::AttachToWindow(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - Menu* self = ObjectWrap::Unwrap(args.This()); if (self == NULL) return node::ThrowError("Menu is already destroyed"); diff --git a/browser/api/atom_api_power_monitor.cc b/browser/api/atom_api_power_monitor.cc index df1ac1f27..1dd362bc6 100644 --- a/browser/api/atom_api_power_monitor.cc +++ b/browser/api/atom_api_power_monitor.cc @@ -39,8 +39,6 @@ void PowerMonitor::OnResume() { // static void PowerMonitor::New(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - if (!args.IsConstructCall()) return node::ThrowError("Require constructor call"); @@ -49,8 +47,6 @@ void PowerMonitor::New(const v8::FunctionCallbackInfo& args) { // static void PowerMonitor::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - #if defined(OS_MACOSX) base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); #endif diff --git a/browser/api/atom_api_protocol.cc b/browser/api/atom_api_protocol.cc index 01dc0de4b..107477d0e 100644 --- a/browser/api/atom_api_protocol.cc +++ b/browser/api/atom_api_protocol.cc @@ -35,6 +35,7 @@ static const char* kEarlyUseProtocolError = "This method can only be used" // Emit an event for the protocol module. void EmitEventInUI(const std::string& event, const std::string& parameter) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); v8::Handle argv[] = { @@ -72,6 +73,7 @@ class CustomProtocolRequestJob : public AdapterRequestJob { virtual void GetJobTypeInUI() OVERRIDE { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); // Call the JS handler. diff --git a/browser/api/atom_api_window.cc b/browser/api/atom_api_window.cc index 9718629db..d5b629683 100644 --- a/browser/api/atom_api_window.cc +++ b/browser/api/atom_api_window.cc @@ -92,6 +92,7 @@ void Window::OnRendererCrashed() { void Window::OnCapturePageDone(const RefCountedV8Function& callback, const std::vector& data) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); v8::Local buffer = node::Buffer::New( @@ -103,8 +104,6 @@ void Window::OnCapturePageDone(const RefCountedV8Function& callback, // static void Window::New(const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - if (!args.IsConstructCall()) return node::ThrowError("Require constructor call"); @@ -625,8 +624,6 @@ void Window::ReloadIgnoringCache( // static void Window::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - v8::Local t = v8::FunctionTemplate::New(Window::New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("BrowserWindow")); diff --git a/browser/api/atom_browser_bindings.cc b/browser/api/atom_browser_bindings.cc index 4b3e79f59..a7753f77a 100644 --- a/browser/api/atom_browser_bindings.cc +++ b/browser/api/atom_browser_bindings.cc @@ -25,6 +25,7 @@ void AtomBrowserBindings::OnRendererMessage(int process_id, int routing_id, const string16& channel, const base::ListValue& args) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); scoped_ptr converter(new V8ValueConverter); @@ -58,6 +59,7 @@ void AtomBrowserBindings::OnRendererMessageSync( const base::ListValue& args, NativeWindow* sender, IPC::Message* message) { + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); scoped_ptr converter(new V8ValueConverter); diff --git a/browser/api/lib/auto-updater.coffee b/browser/api/lib/auto-updater.coffee index 9d0e998b4..81c22f16d 100644 --- a/browser/api/lib/auto-updater.coffee +++ b/browser/api/lib/auto-updater.coffee @@ -4,9 +4,8 @@ EventEmitter = require('events').EventEmitter AutoUpdater::__proto__ = EventEmitter.prototype autoUpdater = new AutoUpdater -autoUpdater.on 'will-install-update-raw', (event, version) -> - @emit 'will-install-update', event, version, => @continueUpdate() -autoUpdater.on 'ready-for-update-on-quit-raw', (event, version) -> - @emit 'ready-for-update-on-quit', event, version, => @quitAndInstall() +autoUpdater.on 'update-downloaded-raw', (args...) -> + args[3] = new Date(args[3]) # releaseDate + @emit 'update-downloaded', args..., => @quitAndInstall() module.exports = autoUpdater diff --git a/browser/atom_browser_client.cc b/browser/atom_browser_client.cc index 19617002a..1f7351c92 100644 --- a/browser/atom_browser_client.cc +++ b/browser/atom_browser_client.cc @@ -4,14 +4,39 @@ #include "browser/atom_browser_client.h" +#include "base/command_line.h" #include "browser/atom_browser_context.h" #include "browser/atom_browser_main_parts.h" +#include "browser/native_window.h" #include "browser/net/atom_url_request_context_getter.h" +#include "browser/window_list.h" +#include "common/options_switches.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/site_instance.h" +#include "content/public/browser/web_contents.h" #include "webkit/common/webpreferences.h" namespace atom { -AtomBrowserClient::AtomBrowserClient() { +namespace { + +struct FindByProcessId { + explicit FindByProcessId(int child_process_id) + : child_process_id_(child_process_id) { + } + + bool operator() (NativeWindow* const window) { + int id = window->GetWebContents()->GetRenderProcessHost()->GetID(); + return id == child_process_id_; + } + + int child_process_id_; +}; + +} // namespace + +AtomBrowserClient::AtomBrowserClient() + : dying_render_process_(NULL) { } AtomBrowserClient::~AtomBrowserClient() { @@ -50,10 +75,44 @@ bool AtomBrowserClient::ShouldSwapProcessesForNavigation( content::SiteInstance* site_instance, const GURL& current_url, const GURL& new_url) { + if (site_instance->HasProcess()) + dying_render_process_ = site_instance->GetProcess(); + // Restart renderer process for all navigations. return true; } +void AtomBrowserClient::AppendExtraCommandLineSwitches( + CommandLine* command_line, + int child_process_id) { + WindowList* list = WindowList::GetInstance(); + NativeWindow* window = NULL; + + // Find the owner of this child process. + WindowList::const_iterator iter = std::find_if( + list->begin(), list->end(), FindByProcessId(child_process_id)); + if (iter != list->end()) + window = *iter; + + // If the render process is a newly started one, which means the window still + // uses the old going-to-be-swapped render process, then we try to find the + // window from the swapped render process. + if (window == NULL && dying_render_process_ != NULL) { + child_process_id = dying_render_process_->GetID(); + WindowList::const_iterator iter = std::find_if( + list->begin(), list->end(), FindByProcessId(child_process_id)); + if (iter != list->end()) + window = *iter; + } + + // Append --node-integration to renderer process. + if (window != NULL) + command_line->AppendSwitchASCII(switches::kNodeIntegration, + window->node_integration()); + + dying_render_process_ = NULL; +} + brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( const content::MainFunctionParams&) { return new AtomBrowserMainParts; diff --git a/browser/atom_browser_client.h b/browser/atom_browser_client.h index 3443f0a70..4fe1131dc 100644 --- a/browser/atom_browser_client.h +++ b/browser/atom_browser_client.h @@ -25,11 +25,16 @@ class AtomBrowserClient : public brightray::BrowserClient { content::SiteInstance* site_instance, const GURL& current_url, const GURL& new_url) OVERRIDE; + virtual void AppendExtraCommandLineSwitches(CommandLine* command_line, + int child_process_id) OVERRIDE; private: virtual brightray::BrowserMainParts* OverrideCreateBrowserMainParts( const content::MainFunctionParams&) OVERRIDE; + // The render process which would be swapped out soon. + content::RenderProcessHost* dying_render_process_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; diff --git a/browser/atom_browser_context.cc b/browser/atom_browser_context.cc index 9f8be6bc0..02d6836e7 100644 --- a/browser/atom_browser_context.cc +++ b/browser/atom_browser_context.cc @@ -61,7 +61,8 @@ AtomURLRequestContextGetter* AtomBrowserContext::CreateRequestContext( GetPath(), BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO), BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE), - CreateNetworkDelegate().Pass(), + base::Bind(&AtomBrowserContext::CreateNetworkDelegate, + base::Unretained(this)), protocol_handlers); resource_context_->set_url_request_context_getter(url_request_getter_.get()); diff --git a/browser/atom_browser_main_parts.cc b/browser/atom_browser_main_parts.cc index 165e76b98..0cb05dd1a 100644 --- a/browser/atom_browser_main_parts.cc +++ b/browser/atom_browser_main_parts.cc @@ -51,6 +51,7 @@ void AtomBrowserMainParts::PostEarlyInitialization() { v8::V8::Initialize(); // Create context. + v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); v8::Local context = v8::Context::New(node_isolate); diff --git a/browser/auto_updater.h b/browser/auto_updater.h index 2166d49f7..9ddbd35b7 100644 --- a/browser/auto_updater.h +++ b/browser/auto_updater.h @@ -19,13 +19,8 @@ class AutoUpdater { static AutoUpdaterDelegate* GetDelegate(); static void SetDelegate(AutoUpdaterDelegate* delegate); - static void Init(); - static void SetFeedURL(const std::string& url); - static void SetAutomaticallyChecksForUpdates(bool yes); - static void SetAutomaticallyDownloadsUpdates(bool yes); static void CheckForUpdates(); - static void CheckForUpdatesInBackground(); private: static AutoUpdaterDelegate* delegate_; diff --git a/browser/auto_updater_delegate.cc b/browser/auto_updater_delegate.cc deleted file mode 100644 index 7b5853ff0..000000000 --- a/browser/auto_updater_delegate.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "browser/auto_updater_delegate.h" - -#include "base/callback.h" - -namespace auto_updater { - -void AutoUpdaterDelegate::WillInstallUpdate(const std::string& version, - const base::Closure& install) { - install.Run(); -} - -void AutoUpdaterDelegate::ReadyForUpdateOnQuit( - const std::string& version, - const base::Closure& quit_and_install) { -} - -} // namespace auto_updater diff --git a/browser/auto_updater_delegate.h b/browser/auto_updater_delegate.h index 2c0e450db..280d3ed0f 100644 --- a/browser/auto_updater_delegate.h +++ b/browser/auto_updater_delegate.h @@ -9,17 +9,32 @@ #include "base/callback_forward.h" +namespace base { +class Time; +} + namespace auto_updater { class AutoUpdaterDelegate { public: - // The application is going to relaunch to install update. - virtual void WillInstallUpdate(const std::string& version, - const base::Closure& install); + // An error happened. + virtual void OnError(const std::string& error) {} - // User has chosen to update on quit. - virtual void ReadyForUpdateOnQuit(const std::string& version, - const base::Closure& quit_and_install); + // Checking to see if there is an update + virtual void OnCheckingForUpdate() {} + + // There is an update available and it is being downloaded + virtual void OnUpdateAvailable() {} + + // There is no available update. + virtual void OnUpdateNotAvailable() {} + + // There is a new update which has been downloaded. + virtual void OnUpdateDownloaded(const std::string& release_notes, + const std::string& release_name, + const base::Time& release_date, + const std::string& update_url, + const base::Closure& quit_and_install) {} protected: virtual ~AutoUpdaterDelegate() {} diff --git a/browser/auto_updater_mac.mm b/browser/auto_updater_mac.mm index 2c622e8f2..290eea5dc 100644 --- a/browser/auto_updater_mac.mm +++ b/browser/auto_updater_mac.mm @@ -4,106 +4,89 @@ #include "browser/auto_updater.h" -// Sparkle's headers are throwing compilation warnings, supress them. -#pragma GCC diagnostic ignored "-Wmissing-method-return-type" -#import +#import +#import +#import +#import #include "base/bind.h" -#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" #include "base/strings/sys_string_conversions.h" #include "browser/auto_updater_delegate.h" -using auto_updater::AutoUpdaterDelegate; +#include + +namespace auto_updater { namespace { -struct NSInvocationDeleter { - inline void operator()(NSInvocation* invocation) const { - [invocation release]; - } -}; +// The gloal SQRLUpdater object. +SQRLUpdater* g_updater = nil; -typedef scoped_ptr ScopedNSInvocation; - -// We are passing the NSInvocation as scoped_ptr, because we want to make sure -// whether or not the callback is called, the NSInvocation should alwasy be -// released, the only way to ensure it is to use scoped_ptr. -void CallNSInvocation(ScopedNSInvocation invocation) { - [invocation.get() invoke]; +void RelaunchToInstallUpdate() { + [[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) { + AutoUpdaterDelegate* delegate = AutoUpdater::GetDelegate(); + if (delegate) + delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription)); + }]; } } // namespace -@interface SUUpdaterDelegate : NSObject { -} -@end - -@implementation SUUpdaterDelegate - -- (BOOL)updater:(SUUpdater*)updater - shouldPostponeRelaunchForUpdate:(SUAppcastItem*)update - untilInvoking:(NSInvocation*)invocation { - AutoUpdaterDelegate* delegate = auto_updater::AutoUpdater::GetDelegate(); - if (!delegate) - return NO; - - std::string version(base::SysNSStringToUTF8([update versionString])); - ScopedNSInvocation invocation_ptr([invocation retain]); - delegate->WillInstallUpdate( - version, - base::Bind(&CallNSInvocation, base::Passed(invocation_ptr.Pass()))); - - return YES; -} - -- (void)updater:(SUUpdater*)updater - willInstallUpdateOnQuit:(SUAppcastItem*)update - immediateInstallationInvocation:(NSInvocation*)invocation { - AutoUpdaterDelegate* delegate = auto_updater::AutoUpdater::GetDelegate(); - if (!delegate) - return; - - std::string version(base::SysNSStringToUTF8([update versionString])); - ScopedNSInvocation invocation_ptr([invocation retain]); - delegate->ReadyForUpdateOnQuit( - version, - base::Bind(&CallNSInvocation, base::Passed(invocation_ptr.Pass()))); -} - -@end - -namespace auto_updater { - // static -void AutoUpdater::Init() { - SUUpdaterDelegate* delegate = [[SUUpdaterDelegate alloc] init]; - [[SUUpdater sharedUpdater] setDelegate:delegate]; -} +void AutoUpdater::SetFeedURL(const std::string& feed) { + if (g_updater == nil) { + // Initialize the SQRLUpdater. + NSURL* url = [NSURL URLWithString:base::SysUTF8ToNSString(feed)]; + NSURLRequest* urlRequest = [NSURLRequest requestWithURL:url]; + g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest]; -// static -void AutoUpdater::SetFeedURL(const std::string& url) { - NSString* url_str(base::SysUTF8ToNSString(url)); - [[SUUpdater sharedUpdater] setFeedURL:[NSURL URLWithString:url_str]]; -} + AutoUpdaterDelegate* delegate = GetDelegate(); + if (!delegate) + return; -// static -void AutoUpdater::SetAutomaticallyChecksForUpdates(bool yes) { - [[SUUpdater sharedUpdater] setAutomaticallyChecksForUpdates:yes]; -} - -// static -void AutoUpdater::SetAutomaticallyDownloadsUpdates(bool yes) { - [[SUUpdater sharedUpdater] setAutomaticallyDownloadsUpdates:yes]; + [[g_updater rac_valuesForKeyPath:@"state" observer:g_updater] + subscribeNext:^(NSNumber *stateNumber) { + int state = [stateNumber integerValue]; + if (state == SQRLUpdaterStateCheckingForUpdate) { + delegate->OnCheckingForUpdate(); + } else if (state == SQRLUpdaterStateDownloadingUpdate) { + delegate->OnUpdateAvailable(); + } + }]; + } } // static void AutoUpdater::CheckForUpdates() { - [[SUUpdater sharedUpdater] checkForUpdates:nil]; -} + AutoUpdaterDelegate* delegate = GetDelegate(); + if (!delegate) + return; -// static -void AutoUpdater::CheckForUpdatesInBackground() { - [[SUUpdater sharedUpdater] checkForUpdatesInBackground]; + [[[[g_updater.checkForUpdatesCommand + execute:nil] + // Send a `nil` after everything... + concat:[RACSignal return:nil]] + // But only take the first value. If an update is sent, we'll get that. + // Otherwise, we'll get our inserted `nil` value. + take:1] + subscribeNext:^(SQRLDownloadedUpdate *downloadedUpdate) { + if (downloadedUpdate) { + SQRLUpdate* update = downloadedUpdate.update; + // There is a new update that has been downloaded. + delegate->OnUpdateDownloaded( + base::SysNSStringToUTF8(update.releaseNotes), + base::SysNSStringToUTF8(update.releaseName), + base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970), + base::SysNSStringToUTF8(update.updateURL.absoluteString), + base::Bind(RelaunchToInstallUpdate)); + } else { + // When the completed event is sent with no update, then we know there + // is no update available. + delegate->OnUpdateNotAvailable(); + } + } error:^(NSError *error) { + delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription)); + }]; } - } // namespace auto_updater diff --git a/browser/auto_updater_win.cc b/browser/auto_updater_win.cc index 845eb45bb..ccdc4ed8e 100644 --- a/browser/auto_updater_win.cc +++ b/browser/auto_updater_win.cc @@ -6,28 +6,12 @@ namespace auto_updater { -// static -void AutoUpdater::Init() { -} - // static void AutoUpdater::SetFeedURL(const std::string& url) { } -// static -void AutoUpdater::SetAutomaticallyChecksForUpdates(bool yes) { -} - -// static -void AutoUpdater::SetAutomaticallyDownloadsUpdates(bool yes) { -} - // static void AutoUpdater::CheckForUpdates() { } -// static -void AutoUpdater::CheckForUpdatesInBackground() { -} - } // namespace auto_updater diff --git a/browser/default_app/main.js b/browser/default_app/main.js index 2aff83e30..b3e3bcb03 100644 --- a/browser/default_app/main.js +++ b/browser/default_app/main.js @@ -1,5 +1,4 @@ var app = require('app'); -var dialog = require('dialog'); var path = require('path'); var optimist = require('optimist'); @@ -9,7 +8,7 @@ app.on('window-all-closed', function() { app.quit(); }); -var argv = optimist(process.argv.slice(1)).argv; +var argv = optimist(process.argv.slice(1)).boolean('ci').argv; // Start the specified app if there is one specified in command line, otherwise // start the default app. diff --git a/browser/lib/init.coffee b/browser/lib/init.coffee index 950d4671a..42e8df0d2 100644 --- a/browser/lib/init.coffee +++ b/browser/lib/init.coffee @@ -1,5 +1,6 @@ fs = require 'fs' path = require 'path' +util = require 'util' # Expose information of current process. process.__atom_type = 'browser' @@ -9,6 +10,11 @@ process.resourcesPath = path.resolve process.argv[1], '..', '..', '..' # we need to restore it here. process.argv.splice 1, 1 +# Pick out switches appended by atom-shell. +startMark = process.argv.indexOf '--atom-shell-switches-start' +endMark = process.argv.indexOf '--atom-shell-switches-end' +process.execArgv = process.argv.splice startMark, endMark - startMark + 1 + # Add browser/api/lib to require's search paths, # which contains javascript part of Atom's built-in libraries. globalPaths = require('module').globalPaths @@ -23,8 +29,10 @@ setImmediate -> if process.platform is 'win32' # Redirect node's console to use our own implementations, since node can not # handle console output when running as GUI program. - console.log = console.error = console.warn = process.log - process.stdout.write = process.stderr.write = process.log + print = (args...) -> + process.log util.format(args...) + console.log = console.error = console.warn = print + process.stdout.write = process.stderr.write = print # Always returns EOF for stdin stream. Readable = require('stream').Readable diff --git a/browser/native_window.cc b/browser/native_window.cc index 7b923adf2..7c47c3122 100644 --- a/browser/native_window.cc +++ b/browser/native_window.cc @@ -48,16 +48,20 @@ NativeWindow::NativeWindow(content::WebContents* web_contents, : content::WebContentsObserver(web_contents), has_frame_(true), is_closed_(false), + node_integration_("all"), + has_dialog_attached_(false), weak_factory_(this), inspectable_web_contents_( brightray::InspectableWebContents::Create(web_contents)) { options->GetBoolean(switches::kFrame, &has_frame_); + // Read icon before window is created. std::string icon; - if (options->GetString(switches::kIcon, &icon)) { - if (!SetIcon(icon)) - LOG(ERROR) << "Failed to set icon to " << icon; - } + if (options->GetString(switches::kIcon, &icon) && !SetIcon(icon)) + LOG(ERROR) << "Failed to set icon to " << icon; + + // Read iframe security before any navigation. + options->GetString(switches::kNodeIntegration, &node_integration_); web_contents->SetDelegate(this); @@ -155,6 +159,10 @@ void NativeWindow::InitFromOptions(base::DictionaryValue* options) { Show(); } +bool NativeWindow::HasModalDialog() { + return has_dialog_attached_; +} + void NativeWindow::OpenDevTools() { inspectable_web_contents()->ShowDevTools(); } diff --git a/browser/native_window.h b/browser/native_window.h index 54cb539d7..0e802fd11 100644 --- a/browser/native_window.h +++ b/browser/native_window.h @@ -54,6 +54,25 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, typedef base::Callback& buffer)> CapturePageCallback; + class DialogScope { + public: + 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(); // Create window with existing WebContents. @@ -100,7 +119,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, virtual void FlashFrame(bool flash) = 0; virtual void SetKiosk(bool kiosk) = 0; virtual bool IsKiosk() = 0; - virtual bool HasModalDialog() = 0; + virtual bool HasModalDialog(); virtual gfx::NativeWindow GetNativeWindow() = 0; virtual bool IsClosed() const { return is_closed_; } @@ -140,6 +159,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, } bool has_frame() const { return has_frame_; } + std::string node_integration() const { return node_integration_; } + + void set_has_dialog_attached(bool has_dialog_attached) { + has_dialog_attached_ = has_dialog_attached; + } protected: explicit NativeWindow(content::WebContents* web_contents, @@ -219,6 +243,12 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, // The windows has been closed. bool is_closed_; + // The security token of iframe. + std::string node_integration_; + + // 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_; diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index 93ad1ff19..481419c69 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -14,7 +14,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/values.h" -#import "browser/ui/atom_event_processing_window.h" +#import "browser/ui/cocoa/event_processing_window.h" #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" #include "common/draggable_region.h" @@ -76,7 +76,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0; @end -@interface AtomNSWindow : AtomEventProcessingWindow { +@interface AtomNSWindow : EventProcessingWindow { @protected atom::NativeWindowMac* shell_; } @@ -440,9 +440,9 @@ void NativeWindowMac::HandleKeyboardEvent( event.type == content::NativeWebKeyboardEvent::Char) return; - AtomEventProcessingWindow* event_window = - static_cast(window()); - DCHECK([event_window isKindOfClass:[AtomEventProcessingWindow class]]); + EventProcessingWindow* event_window = + static_cast(window()); + DCHECK([event_window isKindOfClass:[EventProcessingWindow class]]); [event_window redispatchKeyEvent:event.os_event]; } diff --git a/browser/native_window_win.cc b/browser/native_window_win.cc index a99a4a0b4..fefe1b2b9 100644 --- a/browser/native_window_win.cc +++ b/browser/native_window_win.cc @@ -194,17 +194,6 @@ class NativeWindowFramelessView : public views::NonClientFrameView { DISALLOW_COPY_AND_ASSIGN(NativeWindowFramelessView); }; -bool WindowHasModalDialog(HWND parent, HWND except, HWND after = NULL) { - HWND hwnd = ::FindWindowEx(parent, after, NULL, NULL); - if (hwnd != except && - (::GetWindowLong(hwnd, GWL_STYLE) & (WS_VISIBLE | WS_POPUP))) - return true; - else if (hwnd == NULL) - return false; - else - return WindowHasModalDialog(parent, except, hwnd); -} - } // namespace NativeWindowWin::NativeWindowWin(content::WebContents* web_contents, @@ -370,11 +359,6 @@ bool NativeWindowWin::IsKiosk() { return IsFullscreen(); } -bool NativeWindowWin::HasModalDialog() { - return WindowHasModalDialog(GetNativeWindow(), - GetWebContents()->GetView()->GetNativeView()); -} - gfx::NativeWindow NativeWindowWin::GetNativeWindow() { return window_->GetNativeView(); } @@ -417,7 +401,7 @@ void NativeWindowWin::UpdateDraggableRegions( void NativeWindowWin::HandleKeyboardEvent( content::WebContents*, const content::NativeWebKeyboardEvent& event) { - if (event.type == WebKit::WebInputEvent::KeyUp) { + if (event.type == WebKit::WebInputEvent::RawKeyDown) { ui::Accelerator accelerator( static_cast(event.windowsKeyCode), content::GetModifiersFromNativeWebKeyboardEvent(event)); diff --git a/browser/native_window_win.h b/browser/native_window_win.h index 9d5d8af24..705f4b64b 100644 --- a/browser/native_window_win.h +++ b/browser/native_window_win.h @@ -64,7 +64,6 @@ class NativeWindowWin : public NativeWindow, virtual void FlashFrame(bool flash) OVERRIDE; virtual void SetKiosk(bool kiosk) OVERRIDE; virtual bool IsKiosk() OVERRIDE; - virtual bool HasModalDialog() OVERRIDE; virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; void OnMenuCommand(int position, HMENU menu); diff --git a/browser/net/atom_url_request_context_getter.cc b/browser/net/atom_url_request_context_getter.cc index bc9fe5150..0c5a5c6ec 100644 --- a/browser/net/atom_url_request_context_getter.cc +++ b/browser/net/atom_url_request_context_getter.cc @@ -39,13 +39,13 @@ AtomURLRequestContextGetter::AtomURLRequestContextGetter( const base::FilePath& base_path, base::MessageLoop* io_loop, base::MessageLoop* file_loop, - scoped_ptr network_delegate, + base::Callback(void)> factory, content::ProtocolHandlerMap* protocol_handlers) : base_path_(base_path), io_loop_(io_loop), file_loop_(file_loop), job_factory_(NULL), - network_delegate_(network_delegate.Pass()) { + network_delegate_factory_(factory) { // Must first be created on the UI thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -68,6 +68,7 @@ net::URLRequestContext* AtomURLRequestContextGetter::GetURLRequestContext() { if (!url_request_context_.get()) { url_request_context_.reset(new net::URLRequestContext()); + network_delegate_ = network_delegate_factory_.Run().Pass(); url_request_context_->set_network_delegate(network_delegate_.get()); storage_.reset( new net::URLRequestContextStorage(url_request_context_.get())); @@ -89,6 +90,7 @@ net::URLRequestContext* AtomURLRequestContextGetter::GetURLRequestContext() { net::DhcpProxyScriptFetcherFactory dhcp_factory; storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + storage_->set_transport_security_state(new net::TransportSecurityState); storage_->set_proxy_service( net::CreateProxyServiceUsingV8ProxyResolver( proxy_config_service_.release(), @@ -116,6 +118,8 @@ net::URLRequestContext* AtomURLRequestContextGetter::GetURLRequestContext() { net::HttpNetworkSession::Params network_session_params; network_session_params.cert_verifier = url_request_context_->cert_verifier(); + network_session_params.transport_security_state = + url_request_context_->transport_security_state(); network_session_params.server_bound_cert_service = url_request_context_->server_bound_cert_service(); network_session_params.proxy_service = diff --git a/browser/net/atom_url_request_context_getter.h b/browser/net/atom_url_request_context_getter.h index 51a64d872..f66be82e3 100644 --- a/browser/net/atom_url_request_context_getter.h +++ b/browser/net/atom_url_request_context_getter.h @@ -5,6 +5,7 @@ #ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_ #define ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_ +#include "base/callback.h" #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/content_browser_client.h" @@ -34,7 +35,7 @@ class AtomURLRequestContextGetter : public net::URLRequestContextGetter { const base::FilePath& base_path, base::MessageLoop* io_loop, base::MessageLoop* file_loop, - scoped_ptr network_delegate, + base::Callback(void)>, content::ProtocolHandlerMap* protocol_handlers); // net::URLRequestContextGetter implementations: @@ -53,7 +54,10 @@ class AtomURLRequestContextGetter : public net::URLRequestContextGetter { base::FilePath base_path_; base::MessageLoop* io_loop_; base::MessageLoop* file_loop_; + AtomURLRequestJobFactory* job_factory_; + base::Callback(void)> + network_delegate_factory_; scoped_ptr proxy_config_service_; scoped_ptr network_delegate_; diff --git a/browser/mac/Info.plist b/browser/resources/mac/Info.plist similarity index 95% rename from browser/mac/Info.plist rename to browser/resources/mac/Info.plist index c931513b6..7d42a5a68 100644 --- a/browser/mac/Info.plist +++ b/browser/resources/mac/Info.plist @@ -11,7 +11,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.8.5 + 0.9.2 NSMainNibFile MainMenu NSPrincipalClass diff --git a/browser/mac/atom.icns b/browser/resources/mac/atom.icns similarity index 100% rename from browser/mac/atom.icns rename to browser/resources/mac/atom.icns diff --git a/app/win/atom.ico b/browser/resources/win/atom.ico similarity index 100% rename from app/win/atom.ico rename to browser/resources/win/atom.ico diff --git a/app/win/atom.rc b/browser/resources/win/atom.rc similarity index 90% rename from app/win/atom.rc rename to browser/resources/win/atom.rc index 0d1905693..a0cb10719 100644 --- a/app/win/atom.rc +++ b/browser/resources/win/atom.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,8,5,0 - PRODUCTVERSION 0,8,5,0 + FILEVERSION 0,9,2,0 + PRODUCTVERSION 0,9,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Atom-Shell" - VALUE "FileVersion", "0.8.5" + VALUE "FileVersion", "0.9.2" VALUE "InternalName", "atom.exe" VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "atom.exe" VALUE "ProductName", "Atom-Shell" - VALUE "ProductVersion", "0.8.5" + VALUE "ProductVersion", "0.9.2" END END BLOCK "VarFileInfo" diff --git a/app/win/resource.h b/browser/resources/win/resource.h similarity index 100% rename from app/win/resource.h rename to browser/resources/win/resource.h diff --git a/browser/ui/atom_menu_controller_mac.h b/browser/ui/cocoa/atom_menu_controller.h similarity index 93% rename from browser/ui/atom_menu_controller_mac.h rename to browser/ui/cocoa/atom_menu_controller.h index 834ea9a98..afd60931f 100644 --- a/browser/ui/atom_menu_controller_mac.h +++ b/browser/ui/cocoa/atom_menu_controller.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_UI_ATOM_MENU_CONTROLLER_MAC_H_ -#define ATOM_BROWSER_UI_ATOM_MENU_CONTROLLER_MAC_H_ +#ifndef ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_ +#define ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_ #import @@ -69,4 +69,4 @@ class MenuModel; - (NSMenu*)menuFromModel:(ui::MenuModel*)model; @end -#endif // ATOM_BROWSER_UI_ATOM_MENU_CONTROLLER_MAC_H_ +#endif // ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_ diff --git a/browser/ui/atom_menu_controller_mac.mm b/browser/ui/cocoa/atom_menu_controller.mm similarity index 99% rename from browser/ui/atom_menu_controller_mac.mm rename to browser/ui/cocoa/atom_menu_controller.mm index 13fd73bc1..0a23ab292 100644 --- a/browser/ui/atom_menu_controller_mac.mm +++ b/browser/ui/cocoa/atom_menu_controller.mm @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "browser/ui/atom_menu_controller_mac.h" +#import "browser/ui/cocoa/atom_menu_controller.h" #include "base/logging.h" #include "base/strings/sys_string_conversions.h" diff --git a/browser/ui/atom_event_processing_window.h b/browser/ui/cocoa/event_processing_window.h similarity index 79% rename from browser/ui/atom_event_processing_window.h rename to browser/ui/cocoa/event_processing_window.h index 92a247124..00872a39e 100644 --- a/browser/ui/atom_event_processing_window.h +++ b/browser/ui/cocoa/event_processing_window.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_UI_ATOM_EVENT_PROCESSING_WINDOW_H_ -#define ATOM_BROWSER_UI_ATOM_EVENT_PROCESSING_WINDOW_H_ +#ifndef ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ +#define ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ #import // Override NSWindow to access unhandled keyboard events (for command // processing); subclassing NSWindow is the only method to do // this. -@interface AtomEventProcessingWindow : NSWindow { +@interface EventProcessingWindow : NSWindow { @private BOOL redispatchingEvent_; BOOL eventHandled_; @@ -27,4 +27,4 @@ - (BOOL)performKeyEquivalent:(NSEvent*)theEvent; @end -#endif // ATOM_BROWSER_UI_ATOM_EVENT_PROCESSING_WINDOW_H_ +#endif // ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_ diff --git a/browser/ui/atom_event_processing_window.mm b/browser/ui/cocoa/event_processing_window.mm similarity index 95% rename from browser/ui/atom_event_processing_window.mm rename to browser/ui/cocoa/event_processing_window.mm index ec287fbba..ce6e9b2f3 100644 --- a/browser/ui/atom_event_processing_window.mm +++ b/browser/ui/cocoa/event_processing_window.mm @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "browser/ui/atom_event_processing_window.h" +#import "browser/ui/cocoa/event_processing_window.h" #include "base/logging.h" #import "content/public/browser/render_widget_host_view_mac_base.h" -@interface AtomEventProcessingWindow () +@interface EventProcessingWindow () // Duplicate the given key event, but changing the associated window. - (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event; @end -@implementation AtomEventProcessingWindow +@implementation EventProcessingWindow - (BOOL)redispatchKeyEvent:(NSEvent*)event { DCHECK(event); @@ -103,4 +103,4 @@ return NO; } -@end // AtomEventProcessingWindow +@end // EventProcessingWindow diff --git a/browser/ui/nsalert_synchronous_sheet_mac.h b/browser/ui/cocoa/nsalert_synchronous_sheet.h similarity index 100% rename from browser/ui/nsalert_synchronous_sheet_mac.h rename to browser/ui/cocoa/nsalert_synchronous_sheet.h diff --git a/browser/ui/nsalert_synchronous_sheet_mac.mm b/browser/ui/cocoa/nsalert_synchronous_sheet.mm similarity index 96% rename from browser/ui/nsalert_synchronous_sheet_mac.mm rename to browser/ui/cocoa/nsalert_synchronous_sheet.mm index f2f4d4949..a64652512 100644 --- a/browser/ui/nsalert_synchronous_sheet_mac.mm +++ b/browser/ui/cocoa/nsalert_synchronous_sheet.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "browser/ui/nsalert_synchronous_sheet_mac.h" +#import "browser/ui/cocoa/nsalert_synchronous_sheet.h" // Private methods -- use prefixes to avoid collisions with Apple's methods @interface NSAlert (SynchronousSheetPrivate) diff --git a/browser/ui/file_dialog_win.cc b/browser/ui/file_dialog_win.cc index 1f806dd53..b8b8233db 100644 --- a/browser/ui/file_dialog_win.cc +++ b/browser/ui/file_dialog_win.cc @@ -163,6 +163,7 @@ class FileDialog { } bool Show(atom::NativeWindow* parent_window) { + atom::NativeWindow::DialogScope dialog_scope(parent_window); HWND window = parent_window ? parent_window->GetNativeWindow() : NULL; return dialog_->DoModal(window) == IDOK; } diff --git a/browser/ui/message_box_mac.mm b/browser/ui/message_box_mac.mm index b5d0cc4bb..c6cbed42a 100644 --- a/browser/ui/message_box_mac.mm +++ b/browser/ui/message_box_mac.mm @@ -9,7 +9,7 @@ #include "base/callback.h" #include "base/strings/sys_string_conversions.h" #include "browser/native_window.h" -#include "browser/ui/nsalert_synchronous_sheet_mac.h" +#include "browser/ui/cocoa/nsalert_synchronous_sheet.h" @interface ModalDelegate : NSObject { @private diff --git a/browser/ui/message_box_win.cc b/browser/ui/message_box_win.cc index d77149311..c7a61b8ed 100644 --- a/browser/ui/message_box_win.cc +++ b/browser/ui/message_box_win.cc @@ -76,6 +76,7 @@ class MessageDialog : public base::MessageLoop::Dispatcher, string16 title_; views::Widget* widget_; views::MessageBoxView* message_box_view_; + scoped_ptr dialog_scope_; std::vector buttons_; MessageBoxCallback callback_; @@ -96,7 +97,8 @@ MessageDialog::MessageDialog(NativeWindow* parent_window, result_(-1), title_(UTF8ToUTF16(title)), widget_(NULL), - message_box_view_(NULL) { + message_box_view_(NULL), + dialog_scope_(new NativeWindow::DialogScope(parent_window)) { DCHECK_GT(buttons.size(), 0u); set_owned_by_client(); @@ -174,6 +176,7 @@ string16 MessageDialog::GetWindowTitle() const { void MessageDialog::WindowClosing() { should_close_ = true; + dialog_scope_.reset(); if (delete_on_close_) { callback_.Run(GetResult()); diff --git a/common.gypi b/common.gypi index b6cc25a1c..64dd63d2c 100644 --- a/common.gypi +++ b/common.gypi @@ -223,5 +223,14 @@ }, }, }], # OS=="win" + # The breakdpad on Mac assumes Release_Base configuration. + ['OS=="mac"', { + 'target_defaults': { + 'configurations': { + 'Release_Base': { + }, + }, + }, + }], # OS=="mac" ], } diff --git a/common/api/atom_api_clipboard.cc b/common/api/atom_api_clipboard.cc index e83b1eb54..d0c97d350 100644 --- a/common/api/atom_api_clipboard.cc +++ b/common/api/atom_api_clipboard.cc @@ -74,8 +74,6 @@ void Clipboard::Clear(const v8::FunctionCallbackInfo& args) { // static void Clipboard::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - NODE_SET_METHOD(target, "has", Has); NODE_SET_METHOD(target, "read", Read); NODE_SET_METHOD(target, "readText", ReadText); diff --git a/common/api/atom_api_event_emitter.cc b/common/api/atom_api_event_emitter.cc index f175810ad..998876b05 100644 --- a/common/api/atom_api_event_emitter.cc +++ b/common/api/atom_api_event_emitter.cc @@ -21,6 +21,11 @@ EventEmitter::EventEmitter(v8::Handle wrapper) { } EventEmitter::~EventEmitter() { + // Use Locker in browser process. + scoped_ptr locker; + if (node::g_standalone_mode) + locker.reset(new v8::Locker(node_isolate)); + // Clear the aligned pointer, it should have been done by ObjectWrap but // somehow node v0.11.x changed this behaviour. v8::HandleScope handle_scope(node_isolate); @@ -33,6 +38,11 @@ bool EventEmitter::Emit(const std::string& name) { } bool EventEmitter::Emit(const std::string& name, base::ListValue* args) { + // Use Locker in browser process. + scoped_ptr locker; + if (node::g_standalone_mode) + locker.reset(new v8::Locker(node_isolate)); + v8::HandleScope handle_scope(node_isolate); v8::Handle context = v8::Context::GetCurrent(); diff --git a/common/api/atom_api_id_weak_map.cc b/common/api/atom_api_id_weak_map.cc index 2ee2cf329..09abbe901 100644 --- a/common/api/atom_api_id_weak_map.cc +++ b/common/api/atom_api_id_weak_map.cc @@ -122,8 +122,6 @@ void IDWeakMap::Remove(const v8::FunctionCallbackInfo& args) { // static void IDWeakMap::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - v8::Local t = v8::FunctionTemplate::New(New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("IDWeakMap")); diff --git a/common/api/atom_api_screen.cc b/common/api/atom_api_screen.cc index 329767271..85e1ff2a9 100644 --- a/common/api/atom_api_screen.cc +++ b/common/api/atom_api_screen.cc @@ -67,8 +67,6 @@ void Screen::GetPrimaryDisplay( // static void Screen::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - v8::Local t = v8::FunctionTemplate::New(New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(v8::String::NewSymbol("Screen")); diff --git a/common/api/atom_api_shell.cc b/common/api/atom_api_shell.cc index 5f7f2d80c..63a114b87 100644 --- a/common/api/atom_api_shell.cc +++ b/common/api/atom_api_shell.cc @@ -60,8 +60,6 @@ void Shell::Beep(const v8::FunctionCallbackInfo& args) { // static void Shell::Initialize(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - NODE_SET_METHOD(target, "showItemInFolder", ShowItemInFolder); NODE_SET_METHOD(target, "openItem", OpenItem); NODE_SET_METHOD(target, "openExternal", OpenExternal); diff --git a/common/api/atom_api_v8_util.cc b/common/api/atom_api_v8_util.cc index 01d779c3b..1f3d250af 100644 --- a/common/api/atom_api_v8_util.cc +++ b/common/api/atom_api_v8_util.cc @@ -46,8 +46,6 @@ void TakeHeapSnapshot(const v8::FunctionCallbackInfo& args) { } // namespace void InitializeV8Util(v8::Handle target) { - v8::HandleScope handle_scope(node_isolate); - NODE_SET_METHOD(target, "createObjectWithName", CreateObjectWithName); NODE_SET_METHOD(target, "getHiddenValue", GetHiddenValue); NODE_SET_METHOD(target, "setHiddenValue", SetHiddenValue); diff --git a/common/api/atom_bindings.cc b/common/api/atom_bindings.cc index 8dc3b85a4..060486b45 100644 --- a/common/api/atom_bindings.cc +++ b/common/api/atom_bindings.cc @@ -53,6 +53,13 @@ void UvOnCallback(uv_async_t* handle, int status) { g_v8_callback->NewHandle()->Call(global, 0, NULL); } +// Called when there is a fatal error in V8, we just crash the process here so +// we can get the stack trace. +void FatalErrorCallback(const char* location, const char* message) { + LOG(ERROR) << "Fatal error in V8: " << location << " " << message; + static_cast(NULL)->crash = true; +} + v8::Handle DumpStackFrame(v8::Handle stack_frame) { v8::Local result = v8::Object::New(); result->Set(ToV8Value("line"), ToV8Value(stack_frame->GetLineNumber())); @@ -76,14 +83,13 @@ node::node_module_struct* GetBuiltinModule(const char *name, bool is_browser); AtomBindings::AtomBindings() { uv_async_init(uv_default_loop(), &g_next_tick_uv_handle, UvCallNextTick); uv_async_init(uv_default_loop(), &g_callback_uv_handle, UvOnCallback); + v8::V8::SetFatalErrorHandler(FatalErrorCallback); } AtomBindings::~AtomBindings() { } void AtomBindings::BindTo(v8::Handle process) { - v8::HandleScope handle_scope(node_isolate); - NODE_SET_METHOD(process, "atomBinding", Binding); NODE_SET_METHOD(process, "crash", Crash); NODE_SET_METHOD(process, "activateUvLoop", ActivateUVLoop); @@ -152,18 +158,13 @@ void AtomBindings::ActivateUVLoop( // static void AtomBindings::Log(const v8::FunctionCallbackInfo& args) { - std::string message; - for (int i = 0; i < args.Length(); ++i) - message += *v8::String::Utf8Value(args[i]); - - logging::LogMessage("CONSOLE", 0, 0).stream() << message; + v8::String::Utf8Value str(args[0]); + logging::LogMessage("CONSOLE", 0, 0).stream() << *str; } // static void AtomBindings::GetCurrentStackTrace( const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - int stack_limit = kMaxCallStackSize; FromV8Arguments(args, &stack_limit); diff --git a/common/atom_version.h b/common/atom_version.h index f6786ed1b..505b9470a 100644 --- a/common/atom_version.h +++ b/common/atom_version.h @@ -6,8 +6,8 @@ #define ATOM_VERSION_H #define ATOM_MAJOR_VERSION 0 -#define ATOM_MINOR_VERSION 8 -#define ATOM_PATCH_VERSION 5 +#define ATOM_MINOR_VERSION 9 +#define ATOM_PATCH_VERSION 2 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/common/lib/init.coffee b/common/lib/init.coffee index 48c1b2942..20d468ee6 100644 --- a/common/lib/init.coffee +++ b/common/lib/init.coffee @@ -19,10 +19,3 @@ wrapWithActivateUvLoop = (func) -> process.nextTick = wrapWithActivateUvLoop process.nextTick global.setImmediate = wrapWithActivateUvLoop timers.setImmediate global.clearImmediate = timers.clearImmediate - -# The child_process module also needs to activate the uv loop to make the ipc -# channel setup. -# TODO(zcbenz): Find out why this is needed. -childProcess = require 'child_process' -childProcess.spawn = wrapWithActivateUvLoop childProcess.spawn -childProcess.fork = wrapWithActivateUvLoop childProcess.fork diff --git a/common/node_bindings.cc b/common/node_bindings.cc index e36ba9baf..3d2d5ebcc 100644 --- a/common/node_bindings.cc +++ b/common/node_bindings.cc @@ -194,6 +194,11 @@ void NodeBindings::RunMessageLoop() { void NodeBindings::UvRunOnce() { DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI)); + // Use Locker in browser process. + scoped_ptr locker; + if (is_browser_) + locker.reset(new v8::Locker(node_isolate)); + v8::HandleScope handle_scope(node_isolate); // Enter node context while dealing with uv events, by default the global diff --git a/common/node_bindings_mac.cc b/common/node_bindings_mac.cc index 3397e35a5..0a31a1dd1 100644 --- a/common/node_bindings_mac.cc +++ b/common/node_bindings_mac.cc @@ -26,6 +26,23 @@ NodeBindingsMac::NodeBindingsMac(bool is_browser) NodeBindingsMac::~NodeBindingsMac() { } +void NodeBindingsMac::RunMessageLoop() { + // Get notified when libuv's watcher queue changes. + uv_loop_->data = this; + uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged; + + NodeBindings::RunMessageLoop(); +} + +// static +void NodeBindingsMac::OnWatcherQueueChanged(uv_loop_t* loop) { + NodeBindingsMac* self = static_cast(loop->data); + + // We need to break the io polling in the kqueue thread when loop's watcher + // queue changes, otherwise new events cannot be notified. + self->WakeupEmbedThread(); +} + void NodeBindingsMac::PollEvents() { struct timespec spec; int timeout = uv_backend_timeout(uv_loop_); diff --git a/common/node_bindings_mac.h b/common/node_bindings_mac.h index 6ae79c0a6..4929c1a2c 100644 --- a/common/node_bindings_mac.h +++ b/common/node_bindings_mac.h @@ -15,7 +15,12 @@ class NodeBindingsMac : public NodeBindings { explicit NodeBindingsMac(bool is_browser); virtual ~NodeBindingsMac(); + virtual void RunMessageLoop() OVERRIDE; + private: + // Called when uv's watcher queue changes. + static void OnWatcherQueueChanged(uv_loop_t* loop); + virtual void PollEvents() OVERRIDE; // Kqueue to poll for uv's backend fd. diff --git a/common/options_switches.cc b/common/options_switches.cc index 6f068a19d..f3d849ef1 100644 --- a/common/options_switches.cc +++ b/common/options_switches.cc @@ -31,6 +31,8 @@ const char kKiosk[] = "kiosk"; // Make windows stays on the top of all other windows. const char kAlwaysOnTop[] = "always-on-top"; +const char kNodeIntegration[] = "node-integration"; + } // namespace switches } // namespace atom diff --git a/common/options_switches.h b/common/options_switches.h index ee61044df..ad6b68b2e 100644 --- a/common/options_switches.h +++ b/common/options_switches.h @@ -26,6 +26,7 @@ extern const char kResizable[]; extern const char kFullscreen[]; extern const char kKiosk[]; extern const char kAlwaysOnTop[]; +extern const char kNodeIntegration[]; } // namespace switches diff --git a/common/resources/mac/Info.plist b/common/resources/mac/Info.plist new file mode 100644 index 000000000..e259c9e21 --- /dev/null +++ b/common/resources/mac/Info.plist @@ -0,0 +1,14 @@ + + + + + CFBundleExecutable + Atom Framework + CFBundleIdentifier + com.github.AtomFramework + CFBundleName + Atom Framework + CFBundlePackageType + FMWK + + diff --git a/browser/mac/MainMenu.xib b/common/resources/mac/MainMenu.xib similarity index 100% rename from browser/mac/MainMenu.xib rename to common/resources/mac/MainMenu.xib diff --git a/docs/api/browser/auto-updater.md b/docs/api/browser/auto-updater.md index d78a8720a..903dbc220 100644 --- a/docs/api/browser/auto-updater.md +++ b/docs/api/browser/auto-updater.md @@ -1,42 +1,42 @@ # auto-updater -`auto-updater` module is a simple wrap around the Sparkle framework, it -provides auto update service for the application. +The `auto-updater` module is a simple wrap around the +[Squirrel](https://github.com/Squirrel/Squirrel.Mac) framework, you should +follow Squirrel's instructions on setting the server. -Before using this module, you should edit the `Info.plist` following -https://github.com/andymatuschak/Sparkle/wiki. +## Event: checking-for-update -## Event: will-install-update +Emitted when checking for update has started. + +## Event: update-available + +Emitted when there is an available update, the update would be downloaded +automatically. + +## Event: update-not-available + +Emitted when there is no available update. + +## Event: update-downloaded * `event` Event -* `version` String -* `continueUpdate` Function - -This event is emitted when the update is found and going to be installed. -Calling `event.preventDefault()` would pause it, and you can call -`continueUpdate` to continue the update. - -## Event: ready-for-update-on-quit - -* `event` Event -* `version` String +* `releaseNotes` String +* `releaseName` String +* `releaseDate` Date +* `updateUrl` String * `quitAndUpdate` Function -This event is emitted when user chose to delay the update until the quit. -Calling `quitAndUpdate()` would quit the application and install the update. +Emitted when update has been downloaded, calling `quitAndUpdate()` would restart +the application and install the update. ## autoUpdater.setFeedUrl(url) * `url` String -## autoUpdater.setAutomaticallyChecksForUpdates(flag) - -* `flag` Boolean - -## autoUpdater.setAutomaticallyDownloadsUpdates(flag) - -* `flag` Boolean +Set the `url` and initialize the auto updater. The `url` could not be changed +once it is set. ## autoUpdater.checkForUpdates() -## autoUpdater.checkForUpdatesInBackground() +Ask the server whether there is an update, you have to call `setFeedUrl` before +using this API. diff --git a/docs/api/browser/browser-window.md b/docs/api/browser/browser-window.md index e078fa772..d6ef45380 100644 --- a/docs/api/browser/browser-window.md +++ b/docs/api/browser/browser-window.md @@ -18,9 +18,6 @@ win.show(); You can also create a window without chrome by using [Frameless Window](frameless-window.md) API. - -**Note:** Be careful not to use `window` as the variable name. - ## Class: BrowserWindow `BrowserWindow` is an @@ -44,11 +41,31 @@ You can also create a window without chrome by using * `show` Boolean - Whether window should be shown when created * `frame` Boolean - Specify `false` to create a [Frameless Window](frameless-window.md) + * `node-integration` String - Can be `all`, `except-iframe`, + `manual-enable-iframe` or `disable`. Creates a new `BrowserWindow` with native properties set by the `options`. Usually you only need to set the `width` and `height`, other properties will have decent default values. +By default the `node-integration` option is `all`, which means node integration +is available to the main page and all its iframes. You can also set it to +`except-iframe`, which would disable node integration in all iframes, or +`manual-enable-iframe`, which is like `except-iframe`, but would enable iframes +whose name is suffixed by `-enable-node-integration`. And setting to `disable` +would disable the node integration in both the main page and its iframes. + +An example of enable node integration in iframe with `node-integration` set to +`manual-enable-iframe`: + +```html + + + + + +``` + ### Event: 'page-title-updated' * `event` Event diff --git a/docs/development/source-code-directory-structure.md b/docs/development/source-code-directory-structure.md index 3f46bf630..a583322b7 100644 --- a/docs/development/source-code-directory-structure.md +++ b/docs/development/source-code-directory-structure.md @@ -15,17 +15,24 @@ to understand the source code better. program. * **browser** - The frontend including the main window, UI, and all browser side things. This talks to the renderer to manage web pages. + * **lib** - Javascript part of browser initialization code. * **ui** - Implementation of UI stuff for different platforms. - * **atom** - Initializes the javascript environment of browser. + * **cocoa** - Cocoa specific source code. + * **gtk** - GTK+ specific source code. + * **win** - Windows GUI specific source code. * **default_app** - The default page to show when atom-shell is started without providing an app. * **api** - The implementation of browser side APIs. * **lib** - Javascript part of the API implementation. + * **net** - Network related code. * **renderer** - Code that runs in renderer. + * **lib** - Javascript part of renderer initialization code. * **api** - The implementation of renderer side APIs. * **lib** - Javascript part of the API implementation. * **common** - Code that used by both browser and renderer, including some utility functions and code to integrate node's message loop into Chromium's message loop. + * **lib** - Common Javascript initialization code. + * **v8** - Utility functions for using V8 and node APIs. * **api** - The implementation of common APIs, and foundations of atom-shell's built-in modules. * **lib** - Javascript part of the API implementation. @@ -35,7 +42,7 @@ to understand the source code better. ## Structure of other directories * **vendor** - Build dependencies. -* **tools** - Helper scripts to build atom-shell. +* **tools** - Helper scripts used by gyp files. * **node_modules** - Third party node modules used for building or running specs. * **out** - Output directory for `ninja`. diff --git a/package.json b/package.json index 021684cd0..6a7face50 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { "name": "atom-shell", - "version": "0.8.5", + "version": "0.9.2", "devDependencies": { "coffee-script": "~1.6.3", "coffeelint": "~0.6.1", + "formidable": "~1.0.14", "mocha": "~1.13.0", "pathwatcher": "0.14.0", "q": "0.9.7", - "walkdir": "~0.0.7", "runas": "0.3.0", - "formidable": "~1.0.14", - "temp": "~0.6.0" + "temp": "~0.6.0", + "walkdir": "~0.0.7" }, "private": true, diff --git a/renderer/atom_render_view_observer.cc b/renderer/atom_render_view_observer.cc index 960be5c02..69d811bf5 100644 --- a/renderer/atom_render_view_observer.cc +++ b/renderer/atom_render_view_observer.cc @@ -5,12 +5,14 @@ #include "renderer/atom_render_view_observer.h" #include "common/api/api_messages.h" +#include "content/public/renderer/render_view.h" #include "ipc/ipc_message_macros.h" #include "renderer/api/atom_renderer_bindings.h" #include "renderer/atom_renderer_client.h" #include "third_party/WebKit/public/web/WebDraggableRegion.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebView.h" #include "common/v8/node_common.h" @@ -53,6 +55,13 @@ bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) { void AtomRenderViewObserver::OnBrowserMessage(const string16& channel, const base::ListValue& args) { + if (!render_view()->GetWebView()) + return; + + WebKit::WebFrame* frame = render_view()->GetWebView()->mainFrame(); + if (!renderer_client_->IsNodeBindingEnabled(frame)) + return; + renderer_client_->atom_bindings()->OnBrowserMessage( render_view(), channel, args); } diff --git a/renderer/atom_renderer_client.cc b/renderer/atom_renderer_client.cc index c89b6c256..b5e606a0e 100644 --- a/renderer/atom_renderer_client.cc +++ b/renderer/atom_renderer_client.cc @@ -6,23 +6,52 @@ #include +#include "base/command_line.h" #include "common/node_bindings.h" +#include "common/options_switches.h" #include "renderer/api/atom_renderer_bindings.h" #include "renderer/atom_render_view_observer.h" +#include "third_party/WebKit/public/web/WebFrame.h" #include "common/v8/node_common.h" namespace atom { +namespace { + +const char* kExceptIframe = "except-iframe"; +const char* kManualEnableIframe = "manual-enable-iframe"; +const char* kDisable = "disable"; +const char* kEnableNodeIntegration = "enable-node-integration"; + +} // namespace + AtomRendererClient::AtomRendererClient() - : node_bindings_(NodeBindings::Create(false)), - atom_bindings_(new AtomRendererBindings) { + : node_integration_(ALL), + main_frame_(NULL) { + // Translate the token. + std::string token = CommandLine::ForCurrentProcess()-> + GetSwitchValueASCII(switches::kNodeIntegration); + if (token == kExceptIframe) + node_integration_ = EXCEPT_IFRAME; + else if (token == kManualEnableIframe) + node_integration_ = MANUAL_ENABLE_IFRAME; + else if (token == kDisable) + node_integration_ = DISABLE; + + if (IsNodeBindingEnabled()) { + node_bindings_.reset(NodeBindings::Create(false)); + atom_bindings_.reset(new AtomRendererBindings); + } } AtomRendererClient::~AtomRendererClient() { } void AtomRendererClient::RenderThreadStarted() { + if (!IsNodeBindingEnabled()) + return; + node_bindings_->Initialize(); node_bindings_->PrepareMessageLoop(); @@ -43,6 +72,13 @@ void AtomRendererClient::DidCreateScriptContext(WebKit::WebFrame* frame, v8::Handle context, int extension_group, int world_id) { + // The first web frame is the main frame. + if (main_frame_ == NULL) + main_frame_ = frame; + + if (!IsNodeBindingEnabled(frame)) + return; + v8::Context::Scope scope(context); // Check the existance of process object to prevent duplicate initialization. @@ -70,6 +106,9 @@ void AtomRendererClient::WillReleaseScriptContext( WebKit::WebFrame* frame, v8::Handle context, int world_id) { + if (!IsNodeBindingEnabled(frame)) + return; + node::Environment* env = node::Environment::GetCurrent(context); if (env == NULL) { LOG(ERROR) << "Encounter a non-node context when releasing script context"; @@ -108,4 +147,21 @@ bool AtomRendererClient::ShouldFork(WebKit::WebFrame* frame, return true; } +bool AtomRendererClient::IsNodeBindingEnabled(WebKit::WebFrame* frame) { + if (node_integration_ == DISABLE) + return false; + // Node integration is enabled in main frame unless explictly disabled. + else if (frame == main_frame_) + return true; + else if (node_integration_ == MANUAL_ENABLE_IFRAME && + frame != NULL && + frame->uniqueName().utf8().find(kEnableNodeIntegration) + == std::string::npos) + return false; + else if (node_integration_ == EXCEPT_IFRAME && frame != NULL) + return false; + else + return true; +} + } // namespace atom diff --git a/renderer/atom_renderer_client.h b/renderer/atom_renderer_client.h index 3dde5eb1d..bc7aab740 100644 --- a/renderer/atom_renderer_client.h +++ b/renderer/atom_renderer_client.h @@ -23,9 +23,18 @@ class AtomRendererClient : public content::ContentRendererClient { AtomRendererClient(); virtual ~AtomRendererClient(); + bool IsNodeBindingEnabled(WebKit::WebFrame* frame = NULL); + AtomRendererBindings* atom_bindings() const { return atom_bindings_.get(); } private: + enum NodeIntegration { + ALL, + EXCEPT_IFRAME, + MANUAL_ENABLE_IFRAME, + DISABLE, + }; + virtual void RenderThreadStarted() OVERRIDE; virtual void RenderViewCreated(content::RenderView*) OVERRIDE; virtual void DidCreateScriptContext(WebKit::WebFrame* frame, @@ -47,6 +56,12 @@ class AtomRendererClient : public content::ContentRendererClient { scoped_ptr node_bindings_; scoped_ptr atom_bindings_; + // The level of node integration we should support. + NodeIntegration node_integration_; + + // The main frame. + WebKit::WebFrame* main_frame_; + DISALLOW_COPY_AND_ASSIGN(AtomRendererClient); }; diff --git a/renderer/lib/init.coffee b/renderer/lib/init.coffee index 230529d39..8c061149c 100644 --- a/renderer/lib/init.coffee +++ b/renderer/lib/init.coffee @@ -25,11 +25,12 @@ global.module = module # Set the __filename to the path of html file if it's file:// protocol. if window.location.protocol is 'file:' - global.__filename = + pathname = if process.platform is 'win32' window.location.pathname.substr 1 else window.location.pathname + global.__filename = decodeURIComponent pathname global.__dirname = path.dirname global.__filename # Set module's filename so relative require can work as expected. diff --git a/renderer/mac/Info.plist b/renderer/resources/mac/Info.plist similarity index 100% rename from renderer/mac/Info.plist rename to renderer/resources/mac/Info.plist diff --git a/script/bootstrap.py b/script/bootstrap.py index 10dfde5b3..b4101cd10 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -5,12 +5,12 @@ import os import subprocess import sys +from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL from lib.util import scoped_cwd SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) VENDOR_DIR = os.path.join(SOURCE_ROOT, 'vendor') -BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' PYTHON_26_URL = 'https://chromium.googlesource.com/chromium/deps/python_26' @@ -52,7 +52,8 @@ def update_submodules(): def bootstrap_brightray(url): bootstrap = os.path.join(VENDOR_DIR, 'brightray', 'script', 'bootstrap') - subprocess.check_call([sys.executable, bootstrap, url]) + subprocess.check_call([sys.executable, bootstrap, '--commit', + LIBCHROMIUMCONTENT_COMMIT, url]) def update_apm(): diff --git a/script/bump-version.py b/script/bump-version.py index 5e4d798f9..1baaf3557 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -5,34 +5,51 @@ import re import subprocess import sys +from lib.util import get_atom_shell_version, scoped_cwd + SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def main(): - if len(sys.argv) != 2: - print 'Usage: bump-version.py version' + if len(sys.argv) != 2 or sys.argv[1] == '-h': + print 'Usage: bump-version.py [ | major | minor | patch]' return 1 - version = sys.argv[1] - if version[0] == 'v': - version = version[1:] - versions = parse_version(version) + option = sys.argv[1] + increments = ['major', 'minor', 'patch', 'build'] + if option in increments: + version = get_atom_shell_version() + versions = parse_version(version.split('-')[0]) + versions = increase_version(versions, increments.index(option)) + else: + versions = parse_version(option) - os.chdir(SOURCE_ROOT) - update_package_json(version) - update_win_rc(version, versions) - update_version_h(versions) - update_info_plist(version) - tag_version(version) + version = '.'.join(versions[:3]) + + with scoped_cwd(SOURCE_ROOT): + update_package_json(version) + update_win_rc(version, versions) + update_version_h(versions) + update_info_plist(version) + tag_version(version) + git_push() def parse_version(version): + if version[0] == 'v': + version = version[1:] + vs = version.split('.') if len(vs) > 4: return vs[0:4] else: - return vs + [0] * (4 - len(vs)) + return vs + ['0'] * (4 - len(vs)) + + +def increase_version(versions, index): + versions[index] = str(int(versions[index]) + 1) + return versions def update_package_json(version): @@ -54,7 +71,7 @@ def update_win_rc(version, versions): pattern_fvs = re.compile(' *VALUE "FileVersion", "[0-9.]+"') pattern_pvs = re.compile(' *VALUE "ProductVersion", "[0-9.]+"') - win_rc = os.path.join('app', 'win', 'atom.rc') + win_rc = os.path.join('browser', 'resources', 'win', 'atom.rc') with open(win_rc, 'r') as f: lines = f.readlines() @@ -92,7 +109,7 @@ def update_version_h(versions): def update_info_plist(version): - info_plist = os.path.join('browser', 'mac', 'Info.plist') + info_plist = os.path.join('browser', 'resources', 'mac', 'Info.plist') with open(info_plist, 'r') as f: lines = f.readlines() @@ -112,5 +129,9 @@ def tag_version(version): subprocess.check_call(['git', 'tag', 'v{0}'.format(version)]) +def git_push(): + subprocess.check_call(['git', 'push']) + + if __name__ == '__main__': sys.exit(main()) diff --git a/script/cibuild b/script/cibuild index edabc2df9..d9e8ceb68 100755 --- a/script/cibuild +++ b/script/cibuild @@ -13,6 +13,7 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def main(): rm_rf(os.path.join(SOURCE_ROOT, 'out')) rm_rf(os.path.join(SOURCE_ROOT, 'node_modules')) + rm_rf(os.path.join(SOURCE_ROOT, 'frameworks')) rm_rf(os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor', 'download', 'libchromiumcontent')) diff --git a/script/cpplint.py b/script/cpplint.py index c3d97bc46..e4314142b 100755 --- a/script/cpplint.py +++ b/script/cpplint.py @@ -6,13 +6,13 @@ import subprocess import sys IGNORE_FILES = [ - 'app/win/resource.h', 'browser/atom_application_mac.h', 'browser/atom_application_delegate_mac.h', 'browser/native_window_mac.h', - 'browser/ui/atom_event_processing_window.h', - 'browser/ui/atom_menu_controller_mac.h', - 'browser/ui/nsalert_synchronous_sheet_mac.h', + 'browser/resources/win/resource.h', + 'browser/ui/cocoa/event_processing_window.h', + 'browser/ui/cocoa/atom_menu_controller.h', + 'browser/ui/cocoa/nsalert_synchronous_sheet.h', 'common/api/api_messages.cc', 'common/api/api_messages.h', 'common/atom_version.h', diff --git a/script/create-dist.py b/script/create-dist.py index 5d96a8f0a..d0fd8bcc1 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -7,13 +7,12 @@ import subprocess import sys import tarfile +from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL, NODE_VERSION from lib.util import scoped_cwd, rm_rf, get_atom_shell_version, make_zip, \ safe_mkdir ATOM_SHELL_VRESION = get_atom_shell_version() -NODE_VERSION = 'v0.11.10' -BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) DIST_DIR = os.path.join(SOURCE_ROOT, 'dist') @@ -163,7 +162,8 @@ def download_libchromiumcontent_symbols(url): download = os.path.join(brightray_dir, 'libchromiumcontent', 'script', 'download') - subprocess.check_call([sys.executable, download, '-f', '-s', url, target_dir]) + subprocess.check_call([sys.executable, download, '-f', '-s', '-c', + LIBCHROMIUMCONTENT_COMMIT, url, target_dir]) def create_symbols(): diff --git a/script/lib/config.py b/script/lib/config.py new file mode 100644 index 000000000..5c746e294 --- /dev/null +++ b/script/lib/config.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +NODE_VERSION = 'v0.11.10' +BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' +LIBCHROMIUMCONTENT_COMMIT = 'b27290717c08f8c6a58067d3c3725d68b4e6a2e5' diff --git a/script/translate-crash-log-addresses.coffee b/script/translate-crash-log-addresses.coffee deleted file mode 100755 index 84c05b197..000000000 --- a/script/translate-crash-log-addresses.coffee +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env coffee -# Usage: -# Copy the crash log into pasteboard and then run -# pbpaste | ./script/translate-crash-log-addresses.coffee - -atos = (addresses, callback) -> - path = require 'path' - exec = require('child_process').exec - - exec 'atos -o vendor/brightray/vendor/download/libchromiumcontent/Release/libchromiumcontent.dylib -arch i386 '.concat(addresses...), (error, stdout, stderr) -> - throw error if error? - callback stdout.split('\n') - -parse_stack_trace = (raw) -> - lines = {} - addresses = [] - for line in raw - columns = line.split /\ +/ - if columns[1] == 'libchromiumcontent.dylib' and /0x[a-f0-9]+/.test columns[3] - lines[columns[0]] = addresses.length - addresses.push '0x' + parseInt(columns[5]).toString(16) + ' ' - - atos addresses, (parsed) -> - for line in raw - columns = line.split /\ +/ - frame = columns[0] - if lines[frame]? - console.log frame, parsed[lines[frame]] - else - console.log line - -parse_log_file = (content) -> - state = 'start' - stack_trace = [] - lines = content.split /\r?\n/ - - for line in lines - if state == 'start' - if /Thread \d+ Crashed::/.test line - console.log line - state = 'parse' - else if state == 'parse' - break if line == '' - stack_trace.push line - - parse_stack_trace stack_trace - -input = '' -process.stdin.resume() -process.stdin.setEncoding 'utf8' -process.stdin.on 'data', (chunk) -> - input += chunk -process.stdin.on 'end', -> - parse_log_file input diff --git a/script/update-frameworks.py b/script/update-frameworks.py index e6c311946..f465d0107 100755 --- a/script/update-frameworks.py +++ b/script/update-frameworks.py @@ -7,13 +7,15 @@ from lib.util import safe_mkdir, extract_zip, tempdir, download SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) -FRAMEWORKS_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/frameworks' +FRAMEWORKS_URL = 'http://atom-alpha.s3.amazonaws.com' def main(): os.chdir(SOURCE_ROOT) safe_mkdir('frameworks') - download_and_unzip('Sparkle') + download_and_unzip('Mantle') + download_and_unzip('ReactiveCocoa') + download_and_unzip('Squirrel') def download_and_unzip(framework): diff --git a/script/upload.py b/script/upload.py index c51cc22ea..e93581e58 100755 --- a/script/upload.py +++ b/script/upload.py @@ -8,6 +8,7 @@ import subprocess import sys import tempfile +from lib.config import NODE_VERSION from lib.util import get_atom_shell_version, scoped_cwd, safe_mkdir from lib.github import GitHub @@ -21,7 +22,6 @@ TARGET_PLATFORM = { ATOM_SHELL_REPO = 'atom/atom-shell' ATOM_SHELL_VRESION = get_atom_shell_version() -NODE_VERSION = 'v0.11.10' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release') diff --git a/vendor/apm b/vendor/apm index 35edbb07f..af40a0ed5 160000 --- a/vendor/apm +++ b/vendor/apm @@ -1 +1 @@ -Subproject commit 35edbb07fb4abba49dd97d12a1ad8c4adb71625f +Subproject commit af40a0ed55a5df3e8f7a7707e17ab2493edb94a3 diff --git a/vendor/brightray b/vendor/brightray index d7dd55479..569ea3f1e 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit d7dd5547919eee15e5003c6d05e31183503418ed +Subproject commit 569ea3f1e14b9214528be09dfc2117e387c0a03f diff --git a/vendor/node b/vendor/node index 184a341c2..80c5e17c0 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 184a341c2b959a092f64b168e3d55b11d13583bf +Subproject commit 80c5e17c09fdf2fc0b74353b285bb33a6ecf5e62