From 48ccb0f2ab25719b55798f3c7d7d1351966d6f97 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:23:54 +0800 Subject: [PATCH 01/55] No gfx::SingletonHwnd::Observer any more. Using gfx::SingletonHwndObserver instead. --- .../extensions/global_shortcut_listener_win.cc | 10 ++++++++-- .../extensions/global_shortcut_listener_win.h | 14 +++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc index 248ec6b890e..8ed234d5e81 100644 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc +++ b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc @@ -4,11 +4,14 @@ #include "chrome/browser/extensions/global_shortcut_listener_win.h" +#include "base/bind.h" +#include "base/bind_helpers.h" #include "base/win/win_util.h" #include "content/public/browser/browser_thread.h" #include "ui/base/accelerators/accelerator.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion_win.h" +#include "ui/gfx/win/singleton_hwnd.h" using content::BrowserThread; @@ -35,14 +38,17 @@ GlobalShortcutListenerWin::~GlobalShortcutListenerWin() { void GlobalShortcutListenerWin::StartListening() { DCHECK(!is_listening_); // Don't start twice. DCHECK(!hotkey_ids_.empty()); // Also don't start if no hotkey is registered. - gfx::SingletonHwnd::GetInstance()->AddObserver(this); + singleton_hwnd_observer_.reset(new gfx::SingletonHwndObserver( + base::Bind( + &GlobalShortcutListenerWin::OnWndProc, base::Unretained(this)))); + is_listening_ = true; } void GlobalShortcutListenerWin::StopListening() { DCHECK(is_listening_); // No point if we are not already listening. DCHECK(hotkey_ids_.empty()); // Make sure the map is clean before ending. - gfx::SingletonHwnd::GetInstance()->RemoveObserver(this); + singleton_hwnd_observer_.reset(nullptr); is_listening_ = false; } diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h index a155d8f8991..b3917e9a160 100644 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h +++ b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h @@ -7,26 +7,24 @@ #include +#include "base/memory/scoped_ptr.h" #include "chrome/browser/extensions/global_shortcut_listener.h" #include "ui/gfx/win/singleton_hwnd.h" +#include "ui/gfx/win/singleton_hwnd_observer.h" namespace extensions { // Windows-specific implementation of the GlobalShortcutListener class that // listens for global shortcuts. Handles setting up a keyboard hook and // forwarding its output to the base class for processing. -class GlobalShortcutListenerWin : public GlobalShortcutListener, - public gfx::SingletonHwnd::Observer { +class GlobalShortcutListenerWin : public GlobalShortcutListener { public: GlobalShortcutListenerWin(); virtual ~GlobalShortcutListenerWin(); private: - // The implementation of our Window Proc, called by SingletonHwnd. - virtual void OnWndProc(HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) override; + // The implementation of our Window Proc, called by SingletonHwndObserver. + void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); // GlobalShortcutListener implementation. virtual void StartListening() override; @@ -43,6 +41,8 @@ class GlobalShortcutListenerWin : public GlobalShortcutListener, typedef std::map HotkeyIdMap; HotkeyIdMap hotkey_ids_; + scoped_ptr singleton_hwnd_observer_; + DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerWin); }; From d08392a0c473cc1a11308e13f27ca02a07d15383 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:25:05 +0800 Subject: [PATCH 02/55] No need `base/float_util.h` since VS2013 supports well enough. --- chromium_src/chrome/browser/speech/tts_controller_impl.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chromium_src/chrome/browser/speech/tts_controller_impl.cc b/chromium_src/chrome/browser/speech/tts_controller_impl.cc index 272cafddb94..6b66b6a6196 100644 --- a/chromium_src/chrome/browser/speech/tts_controller_impl.cc +++ b/chromium_src/chrome/browser/speech/tts_controller_impl.cc @@ -7,7 +7,6 @@ #include #include -#include "base/float_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/speech/tts_platform.h" @@ -461,4 +460,4 @@ void TtsControllerImpl::SetTtsEngineDelegate( TtsEngineDelegate* TtsControllerImpl::GetTtsEngineDelegate() { return tts_engine_delegate_; -} \ No newline at end of file +} From 8fda1752641fcf485f51d192922f8f492e5b4a8c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:33:38 +0800 Subject: [PATCH 03/55] Update base::Value::CreateNullValue API changes. --- atom/common/native_mate_converters/v8_value_converter.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index 87bc2e7c030..0d5a2576547 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -211,7 +211,7 @@ base::Value* V8ValueConverter::FromV8ValueImpl( return NULL; if (val->IsNull()) - return base::Value::CreateNullValue(); + return base::Value::CreateNullValue().release(); if (val->IsBoolean()) return new base::FundamentalValue(val->ToBoolean()->Value()); @@ -271,7 +271,7 @@ base::Value* V8ValueConverter::FromV8Array( FromV8ValueState* state, v8::Isolate* isolate) const { if (!state->UpdateAndCheckUniqueness(val)) - return base::Value::CreateNullValue(); + return base::Value::CreateNullValue().release(); scoped_ptr scope; // If val was created in a different context than our current one, change to @@ -310,7 +310,7 @@ base::Value* V8ValueConverter::FromV8Object( FromV8ValueState* state, v8::Isolate* isolate) const { if (!state->UpdateAndCheckUniqueness(val)) - return base::Value::CreateNullValue(); + return base::Value::CreateNullValue().release(); scoped_ptr scope; // If val was created in a different context than our current one, change to From d003b1bb578cd1ee9f763a126da0e97758254ed2 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:39:37 +0800 Subject: [PATCH 04/55] LoadV8Snapshot has been moved from gin::IsolateHolder to gin::V8Initializer. --- atom/app/node_main.cc | 3 ++- atom/browser/javascript_environment.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc index 7446a0a7110..fe4f3fcbfa1 100644 --- a/atom/app/node_main.cc +++ b/atom/app/node_main.cc @@ -8,6 +8,7 @@ #include "atom/common/node_includes.h" #include "gin/array_buffer.h" #include "gin/public/isolate_holder.h" +#include "gin/v8_initializer.h" namespace atom { @@ -19,7 +20,7 @@ int NodeMain(int argc, char *argv[]) { int exit_code = 1; { - gin::IsolateHolder::LoadV8Snapshot(); + gin::V8Initializer::LoadV8Snapshot(); gin::IsolateHolder::Initialize( gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index 887c59353ae..3788fcad8b6 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -5,6 +5,7 @@ #include "atom/browser/javascript_environment.h" #include "gin/array_buffer.h" +#include "gin/v8_initializer.h" namespace atom { @@ -19,7 +20,7 @@ JavascriptEnvironment::JavascriptEnvironment() } bool JavascriptEnvironment::Initialize() { - gin::IsolateHolder::LoadV8Snapshot(); + gin::V8Initializer::LoadV8Snapshot(); gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::ArrayBufferAllocator::SharedInstance()); return true; From fc4031ec264294e63238a0f13dc702de44e7ed96 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:41:51 +0800 Subject: [PATCH 05/55] Now the value in ScopedPtrHashMap is required to be scoped_ptr. --- atom/common/asar/archive.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index 2acd17fd7ab..dda7aa78e0c 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -73,7 +73,8 @@ class Archive { scoped_ptr header_; // Cached external temporary files. - base::ScopedPtrHashMap external_files_; + base::ScopedPtrHashMap> + external_files_; DISALLOW_COPY_AND_ASSIGN(Archive); }; From 46c7ba734b6b63dcf241cf33e5bd595969f265dc Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:46:11 +0800 Subject: [PATCH 06/55] Fix WillAttach API changes in content::BrowserPluginGuestDelegate. --- atom/browser/web_view_guest_delegate.cc | 3 ++- atom/browser/web_view_guest_delegate.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/atom/browser/web_view_guest_delegate.cc b/atom/browser/web_view_guest_delegate.cc index 38f4da4c1f9..efa21421c0d 100644 --- a/atom/browser/web_view_guest_delegate.cc +++ b/atom/browser/web_view_guest_delegate.cc @@ -158,7 +158,8 @@ void WebViewGuestDelegate::SetGuestHost(content::GuestHost* guest_host) { void WebViewGuestDelegate::WillAttach( content::WebContents* embedder_web_contents, int element_instance_id, - bool is_full_page_plugin) { + bool is_full_page_plugin, + const base::Closure& completion_callback) { embedder_web_contents_ = embedder_web_contents; is_full_page_plugin_ = is_full_page_plugin; } diff --git a/atom/browser/web_view_guest_delegate.h b/atom/browser/web_view_guest_delegate.h index 3312b46104a..65e0bcde191 100644 --- a/atom/browser/web_view_guest_delegate.h +++ b/atom/browser/web_view_guest_delegate.h @@ -70,7 +70,8 @@ class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate, void SetGuestHost(content::GuestHost* guest_host) final; void WillAttach(content::WebContents* embedder_web_contents, int element_instance_id, - bool is_full_page_plugin) final; + bool is_full_page_plugin, + const base::Closure& completion_callback) final; private: // This method is invoked when the contents auto-resized to give the container From 11ffb9dfb6898f24a26a40e767c17b6bd83783f8 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 16:50:33 +0800 Subject: [PATCH 07/55] Fix node::Buffer API changes. --- atom/common/api/atom_api_native_image.cc | 13 +++++++------ .../printing/print_preview_message_handler.cc | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/atom/common/api/atom_api_native_image.cc b/atom/common/api/atom_api_native_image.cc index 40a73a7de3f..79fc0c0d6b1 100644 --- a/atom/common/api/atom_api_native_image.cc +++ b/atom/common/api/atom_api_native_image.cc @@ -148,17 +148,18 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder( v8::Local NativeImage::ToPNG(v8::Isolate* isolate) { scoped_refptr png = image_.As1xPNGBytes(); - return node::Buffer::New(isolate, - reinterpret_cast(png->front()), - png->size()); + return node::Buffer::Copy(isolate, + reinterpret_cast(png->front()), + static_cast(png->size())).ToLocalChecked(); } v8::Local NativeImage::ToJPEG(v8::Isolate* isolate, int quality) { std::vector output; gfx::JPEG1xEncodedDataFromImage(image_, quality, &output); - return node::Buffer::New(isolate, - reinterpret_cast(&output.front()), - output.size()); + return node::Buffer::Copy( + isolate, + reinterpret_cast(&output.front()), + static_cast(output.size())).ToLocalChecked(); } std::string NativeImage::ToDataURL() { diff --git a/chromium_src/chrome/browser/printing/print_preview_message_handler.cc b/chromium_src/chrome/browser/printing/print_preview_message_handler.cc index ca70ac2c58e..613f3f2343c 100644 --- a/chromium_src/chrome/browser/printing/print_preview_message_handler.cc +++ b/chromium_src/chrome/browser/printing/print_preview_message_handler.cc @@ -125,8 +125,8 @@ void PrintPreviewMessageHandler::RunPrintToPDFCallback( v8::Locker locker(isolate); v8::HandleScope handle_scope(isolate); if (data) { - v8::Local buffer = node::Buffer::Use(isolate, - data, static_cast(data_size)); + v8::Local buffer = node::Buffer::New(isolate, + data, static_cast(data_size)).ToLocalChecked(); print_to_pdf_callback_map_[request_id].Run(v8::Null(isolate), buffer); } else { v8::Local error_message = v8::String::NewFromUtf8(isolate, From 0e8a585157441358fac9e5a1ec389337f003ac17 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 17:07:31 +0800 Subject: [PATCH 08/55] Fix content::BrowserPluginDelegate::DidResizeElement API changes. Chromium has removed old_size in DidResizeElement interface as the 'old_size' is internal. --- atom/renderer/guest_view_container.cc | 6 ++---- atom/renderer/guest_view_container.h | 6 ++---- atom/renderer/lib/web-view/web-view.coffee | 4 +--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/atom/renderer/guest_view_container.cc b/atom/renderer/guest_view_container.cc index 7643f72b0e5..c0bc1427d68 100644 --- a/atom/renderer/guest_view_container.cc +++ b/atom/renderer/guest_view_container.cc @@ -47,14 +47,12 @@ void GuestViewContainer::SetElementInstanceID(int element_instance_id) { std::make_pair(element_instance_id, this)); } -void GuestViewContainer::DidResizeElement(const gfx::Size& old_size, - const gfx::Size& new_size) { +void GuestViewContainer::DidResizeElement(const gfx::Size& new_size) { if (element_resize_callback_.is_null()) return; base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(element_resize_callback_, old_size, new_size)); + FROM_HERE, base::Bind(element_resize_callback_, new_size)); } } // namespace atom diff --git a/atom/renderer/guest_view_container.h b/atom/renderer/guest_view_container.h index b81f84cbd05..2846265cb2a 100644 --- a/atom/renderer/guest_view_container.h +++ b/atom/renderer/guest_view_container.h @@ -16,8 +16,7 @@ namespace atom { class GuestViewContainer : public content::BrowserPluginDelegate { public: - typedef base::Callback - ResizeCallback; + typedef base::Callback ResizeCallback; explicit GuestViewContainer(content::RenderFrame* render_frame); ~GuestViewContainer() override; @@ -28,8 +27,7 @@ class GuestViewContainer : public content::BrowserPluginDelegate { // content::BrowserPluginDelegate: void SetElementInstanceID(int element_instance_id) final; - void DidResizeElement(const gfx::Size& old_size, - const gfx::Size& new_size) final; + void DidResizeElement(const gfx::Size& new_size) final; private: int element_instance_id_; diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 35fbe17796f..f5bcf0496f8 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -123,11 +123,9 @@ class WebViewImpl # changed. @dispatchEvent webViewEvent - onElementResize: (oldSize, newSize) -> + onElementResize: (newSize) -> # Dispatch the 'resize' event. resizeEvent = new Event('resize', bubbles: true) - resizeEvent.oldWidth = oldSize.width - resizeEvent.oldHeight = oldSize.height resizeEvent.newWidth = newSize.width resizeEvent.newHeight = newSize.height @dispatchEvent resizeEvent From f9fee9174aa96b9768d47552566eea9318c43db3 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 17:10:35 +0800 Subject: [PATCH 09/55] net::URLFetcher::Create now returns object with scoped_ptr. --- atom/browser/net/url_request_fetch_job.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index ee4c67b371e..47ca0633c6c 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -90,7 +90,7 @@ URLRequestFetchJob::URLRequestFetchJob( else request_type = GetRequestType(method); - fetcher_.reset(net::URLFetcher::Create(url, request_type, this)); + fetcher_ = net::URLFetcher::Create(url, request_type, this); // Use request context if provided else create one. if (request_context_getter) fetcher_->SetRequestContext(request_context_getter.get()); From 4e3187fbbda3bd1742881987a8bf2326a6c29b77 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Aug 2015 17:16:08 +0800 Subject: [PATCH 10/55] No need to specify ffmpeg library as it's a normal built library in libchromiumcontent. --- atom.gyp | 3 --- 1 file changed, 3 deletions(-) diff --git a/atom.gyp b/atom.gyp index d24f193ac2d..99ae12452ac 100644 --- a/atom.gyp +++ b/atom.gyp @@ -144,7 +144,6 @@ 'destination': '<(PRODUCT_DIR)', 'files': [ '<@(copied_libraries)', - '<(libchromiumcontent_dir)/ffmpegsumo.dll', '<(libchromiumcontent_dir)/libEGL.dll', '<(libchromiumcontent_dir)/libGLESv2.dll', '<(libchromiumcontent_dir)/icudtl.dat', @@ -193,7 +192,6 @@ 'destination': '<(PRODUCT_DIR)', 'files': [ '<@(copied_libraries)', - '<(libchromiumcontent_dir)/libffmpegsumo.so', '<(libchromiumcontent_dir)/icudtl.dat', '<(libchromiumcontent_dir)/content_shell.pak', '<(libchromiumcontent_dir)/natives_blob.bin', @@ -441,7 +439,6 @@ 'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Libraries', 'files': [ '<@(copied_libraries)', - '<(libchromiumcontent_dir)/ffmpegsumo.so', ], }, { From 28093a4d2d6b3eae728a1764f21fcdc8cb3db63e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 6 Aug 2015 15:03:04 +0800 Subject: [PATCH 11/55] Fix a crash issue in GetProcessOwner if no renderer view host is found. --- atom/browser/atom_browser_client.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 65fd7cd031d..9a3ad00fa4c 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -58,11 +58,15 @@ enum ProcessOwner { OWNER_GUEST_WEB_CONTENTS, OWNER_NONE, // it might be devtools though. }; + ProcessOwner GetProcessOwner(int process_id, NativeWindow** window, WebViewManager::WebViewInfo* info) { - auto web_contents = content::WebContents::FromRenderViewHost( - content::RenderViewHost::FromID(process_id, kDefaultRoutingID)); + content::RenderViewHost* rvh = content::RenderViewHost::FromID( + process_id, kDefaultRoutingID); + if (!rvh) + return OWNER_NONE; + auto web_contents = content::WebContents::FromRenderViewHost(rvh); if (!web_contents) return OWNER_NONE; From c5e540823b30efde052acfe04fc9a96cfdfc8683 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 09:50:19 +0800 Subject: [PATCH 12/55] Update to Chrome 44 --- script/lib/config.py | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index 1298651b7ed..c30e5544075 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'dd51a41b42246b0b5159bfad5e327c8cf10bc585' +LIBCHROMIUMCONTENT_COMMIT = '86d7fcb507e76a917840c31c37b32e501e16a1d4' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/brightray b/vendor/brightray index f4470ee48a7..3f4895f3fd7 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit f4470ee48a748888bccba21845bfd65caaa1a6ce +Subproject commit 3f4895f3fd7cb2ec415b259c2808005512dec57f From 5c57f92ba53b8a3d7ee462f52c0f45dfdf06353e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 09:58:36 +0800 Subject: [PATCH 13/55] Update io.js to v3.0.0 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index 7888f607ce7..02d6e45de63 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 7888f607ce74cc100ceb78f3af258a55ee2f62c4 +Subproject commit 02d6e45de63d4bbb133cc73ab3937e5115fb4ddd From 4337c07425e441c35c0a88f080be4384e5e40deb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 10:02:46 +0800 Subject: [PATCH 14/55] Define node_byteorder and node_release_urlbase --- common.gypi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common.gypi b/common.gypi index 84c2b6c9826..0735d99dd91 100644 --- a/common.gypi +++ b/common.gypi @@ -12,6 +12,8 @@ 'python': 'python', 'openssl_fips': '', 'openssl_no_asm': 1, + 'node_release_urlbase': 'https://atom.io/download/atom-shell', + 'node_byteorder': ' Date: Tue, 11 Aug 2015 10:08:34 +0800 Subject: [PATCH 15/55] Fix compilation warnings caused by chrome44 update --- atom/app/node_main.cc | 3 ++- vendor/brightray | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc index fe4f3fcbfa1..8823e583107 100644 --- a/atom/app/node_main.cc +++ b/atom/app/node_main.cc @@ -5,11 +5,12 @@ #include "atom/app/node_main.h" #include "atom/browser/javascript_environment.h" -#include "atom/common/node_includes.h" #include "gin/array_buffer.h" #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[]) { diff --git a/vendor/brightray b/vendor/brightray index 3f4895f3fd7..618311bc705 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 3f4895f3fd7cb2ec415b259c2808005512dec57f +Subproject commit 618311bc70531ae51b7e2daf65d9c6fc01bf0582 From cc34bc844d11562b6c5404d836ed9a4aaedece6f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 10:10:07 +0800 Subject: [PATCH 16/55] Tell compiler we want to ignore result of SetPrototype --- atom/browser/api/event_emitter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/event_emitter.cc b/atom/browser/api/event_emitter.cc index aa0b6c8781a..be7018dafa4 100644 --- a/atom/browser/api/event_emitter.cc +++ b/atom/browser/api/event_emitter.cc @@ -56,7 +56,7 @@ v8::Local EventEmitter::CreateJSEvent( v8::Local EventEmitter::CreateCustomEvent( v8::Isolate* isolate, v8::Local custom_event) { v8::Local event = CreateEventObject(isolate); - event->SetPrototype(custom_event->CreationContext(), custom_event); + (void)event->SetPrototype(custom_event->CreationContext(), custom_event); mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate)); return event; } From e43c63ae088bd63947c8ac49b6b70f44aa129c68 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 10:25:27 +0800 Subject: [PATCH 17/55] Update chrome_version.h --- atom/common/chrome_version.h | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/common/chrome_version.h b/atom/common/chrome_version.h index 093ed4e98b0..54dd6bb5bb1 100644 --- a/atom/common/chrome_version.h +++ b/atom/common/chrome_version.h @@ -8,7 +8,7 @@ #ifndef ATOM_COMMON_CHROME_VERSION_H_ #define ATOM_COMMON_CHROME_VERSION_H_ -#define CHROME_VERSION_STRING "43.0.2357.65" +#define CHROME_VERSION_STRING "44.0.2403.125" #define CHROME_VERSION "v" CHROME_VERSION_STRING #endif // ATOM_COMMON_CHROME_VERSION_H_ diff --git a/vendor/brightray b/vendor/brightray index 618311bc705..57d15371252 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 618311bc70531ae51b7e2daf65d9c6fc01bf0582 +Subproject commit 57d15371252d85a667316534a6da34f3df654380 From bc0619540950deeb09c10590f37d56e2c2a1069d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 10:40:02 +0800 Subject: [PATCH 18/55] Link with a few more static libraries on Linux and OS X --- script/lib/config.py | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index c30e5544075..2c6d1a3b29c 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '86d7fcb507e76a917840c31c37b32e501e16a1d4' +LIBCHROMIUMCONTENT_COMMIT = '01345b4ef5f2a766e6f58dbbe7729fb089b357ba' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/brightray b/vendor/brightray index 57d15371252..46b093d5147 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 57d15371252d85a667316534a6da34f3df654380 +Subproject commit 46b093d514750aee66092ec64defe7bd8e1bc74d From 2dc533c4b9370e488f87d37c56737064ad2701a5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 10:55:27 +0800 Subject: [PATCH 19/55] Fix search path of ffmpeg It is somehow set to @load_path by Chromium. --- atom.gyp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/atom.gyp b/atom.gyp index 99ae12452ac..cabb43d4f70 100644 --- a/atom.gyp +++ b/atom.gyp @@ -459,6 +459,16 @@ '${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework', ], }, + { + 'postbuild_name': 'Fix path of ffmpeg', + 'action': [ + 'install_name_tool', + '-change', + '@loader_path/libffmpeg.dylib', + '@rpath/libffmpeg.dylib', + '${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework', + ], + }, { 'postbuild_name': 'Add symlinks for framework subdirectories', 'action': [ From 0f990d40ccc9eb47df66c518bb166a95e5e6b5e3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 12:31:41 +0800 Subject: [PATCH 20/55] Use blink's allocator in Node's Buffer --- atom/renderer/atom_renderer_client.cc | 15 +++++++++++++++ script/lib/config.py | 2 +- vendor/node | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 0311f8b540b..af526df9f75 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -24,6 +24,7 @@ #include "third_party/WebKit/public/web/WebPluginParams.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "third_party/WebKit/Source/wtf/ArrayBufferContents.h" #include "atom/common/node_includes.h" @@ -52,6 +53,17 @@ bool IsGuestFrame(blink::WebFrame* frame) { return frame->uniqueName().utf8() == "ATOM_SHELL_GUEST_WEB_VIEW"; } +void* BlinkAllocate(size_t size) { + void* ptr = nullptr; + WTF::ArrayBufferContents::allocateMemory( + size, WTF::ArrayBufferContents::DontInitialize, ptr); + return ptr; +} + +void BlinkFree(void* ptr, size_t size) { + WTF::ArrayBufferContents::freeMemory(ptr, size); +} + // Helper class to forward the messages to the client. class AtomRenderFrameObserver : public content::RenderFrameObserver { public: @@ -91,6 +103,9 @@ void AtomRendererClient::WebKitInitialized() { blink::WebCustomElement::addEmbedderCustomElementName("webview"); blink::WebCustomElement::addEmbedderCustomElementName("browserplugin"); + // Override Node's Buffer allocator with WTF's allocator. + node::Buffer::SetAllocator(&BlinkAllocate, &BlinkFree); + node_bindings_->Initialize(); node_bindings_->PrepareMessageLoop(); diff --git a/script/lib/config.py b/script/lib/config.py index 2c6d1a3b29c..7132b9d63bf 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '01345b4ef5f2a766e6f58dbbe7729fb089b357ba' +LIBCHROMIUMCONTENT_COMMIT = '21768a17f4f1203a50df5c0908b788fa2ecb96ab' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/node b/vendor/node index 02d6e45de63..6472143e364 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 02d6e45de63d4bbb133cc73ab3937e5115fb4ddd +Subproject commit 6472143e364343f73ee6a9e1b67902cc5c30f7ef From e6a2b0a479391a09a148e2fb7ceac0f4a742cc4f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 15:39:17 +0800 Subject: [PATCH 21/55] Fix finding the WebContents of a pending renderer process Apparently after Chrome 44 a renderer process can be started before the corresponding render view is created, though it can be patched but from the source code Chromium is enforcing this everywhere now, so fixing it on our side seems the only reliable solution. This fix is very similar to what we did, but instead of blindly setting swapped process, we now remember which process the pending process is going to replace, so we should not have those race conditions. --- atom/browser/atom_browser_client.cc | 37 +++++++++++++++++++++-------- atom/browser/atom_browser_client.h | 14 +++++++++-- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 9a3ad00fa4c..6b341927229 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -20,6 +20,7 @@ #include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/files/file_util.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/string_number_conversions.h" #include "chrome/browser/printing/printing_message_filter.h" @@ -62,20 +63,14 @@ enum ProcessOwner { ProcessOwner GetProcessOwner(int process_id, NativeWindow** window, WebViewManager::WebViewInfo* info) { - content::RenderViewHost* rvh = content::RenderViewHost::FromID( - process_id, kDefaultRoutingID); - if (!rvh) - return OWNER_NONE; - auto web_contents = content::WebContents::FromRenderViewHost(rvh); + content::WebContents* web_contents = content::WebContents::FromRenderViewHost( + content::RenderViewHost::FromID(process_id, kDefaultRoutingID)); if (!web_contents) return OWNER_NONE; // First search for NativeWindow. - for (auto native_window : *WindowList::GetInstance()) - if (web_contents == native_window->web_contents()) { - *window = native_window; - return OWNER_NATIVE_WINDOW; - } + if ((*window = NativeWindow::FromWebContents(web_contents))) + return OWNER_NATIVE_WINDOW; // Then search for guest WebContents. if (WebViewManager::GetInfoForWebContents(web_contents, info)) @@ -189,6 +184,13 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation( return; *new_instance = content::SiteInstance::CreateForURL(browser_context, url); + + // Remember the original renderer process of the pending renderer process. + auto current_process = current_instance->GetProcess(); + auto pending_process = (*new_instance)->GetProcess(); + pending_processes_[pending_process->GetID()] = current_process->GetID(); + // Clear the entry in map when process ends. + current_process->AddObserver(this); } void AtomBrowserClient::AppendExtraCommandLineSwitches( @@ -212,6 +214,10 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( } #endif + // If the process is a pending process, we should use the old one. + if (ContainsKey(pending_processes_, process_id)) + process_id = pending_processes_[process_id]; + NativeWindow* window; WebViewManager::WebViewInfo info; ProcessOwner owner = GetProcessOwner(process_id, &window, &info); @@ -268,4 +274,15 @@ brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( return new AtomBrowserMainParts; } +void AtomBrowserClient::RenderProcessHostDestroyed( + content::RenderProcessHost* host) { + int process_id = host->GetID(); + for (const auto& entry : pending_processes_) { + if (entry.first == process_id || entry.second == process_id) { + pending_processes_.erase(entry.first); + break; + } + } +} + } // namespace atom diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index f403a519d2f..a0217efede9 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -5,10 +5,12 @@ #ifndef ATOM_BROWSER_ATOM_BROWSER_CLIENT_H_ #define ATOM_BROWSER_ATOM_BROWSER_CLIENT_H_ +#include #include #include #include "brightray/browser/browser_client.h" +#include "content/public/browser/render_process_host_observer.h" namespace content { class QuotaPermissionContext; @@ -21,7 +23,8 @@ class SSLCertRequestInfo; namespace atom { -class AtomBrowserClient : public brightray::BrowserClient { +class AtomBrowserClient : public brightray::BrowserClient, + public content::RenderProcessHostObserver { public: AtomBrowserClient(); virtual ~AtomBrowserClient(); @@ -54,10 +57,17 @@ class AtomBrowserClient : public brightray::BrowserClient { net::SSLCertRequestInfo* cert_request_info, scoped_ptr delegate) override; - private: + // brightray::BrowserClient: brightray::BrowserMainParts* OverrideCreateBrowserMainParts( const content::MainFunctionParams&) override; + // content::RenderProcessHostObserver: + void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; + + private: + // pending_render_process => current_render_process. + std::map pending_processes_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; From a8681b00729b13ed7a72f7575e25e01dda35af19 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 15:59:16 +0800 Subject: [PATCH 22/55] Fix emitting did-attach event --- atom/browser/web_view_guest_delegate.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/web_view_guest_delegate.cc b/atom/browser/web_view_guest_delegate.cc index efa21421c0d..8e1810c4a39 100644 --- a/atom/browser/web_view_guest_delegate.cc +++ b/atom/browser/web_view_guest_delegate.cc @@ -162,6 +162,7 @@ void WebViewGuestDelegate::WillAttach( const base::Closure& completion_callback) { embedder_web_contents_ = embedder_web_contents; is_full_page_plugin_ = is_full_page_plugin; + completion_callback.Run(); } void WebViewGuestDelegate::GuestSizeChangedDueToAutoSize( From 1e9eaba4233057c6517871c409cc68a98a34f183 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 11 Aug 2015 23:38:59 +0800 Subject: [PATCH 23/55] win: Fix compiler warning --- atom/browser/atom_browser_client.cc | 3 ++- script/lib/config.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 6b341927229..f116af0a667 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -69,7 +69,8 @@ ProcessOwner GetProcessOwner(int process_id, return OWNER_NONE; // First search for NativeWindow. - if ((*window = NativeWindow::FromWebContents(web_contents))) + *window = NativeWindow::FromWebContents(web_contents); + if (window) return OWNER_NATIVE_WINDOW; // Then search for guest WebContents. diff --git a/script/lib/config.py b/script/lib/config.py index 7132b9d63bf..9a5979bdbae 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '21768a17f4f1203a50df5c0908b788fa2ecb96ab' +LIBCHROMIUMCONTENT_COMMIT = 'e667b7cc5a04bc8e64960d47079d99446a263e85' PLATFORM = { 'cygwin': 'win32', From 96d53d279ec79bcd86e53b7f1aeb840ca32774c5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 13:30:19 +0800 Subject: [PATCH 24/55] Initial implementation of new protocol API --- atom/browser/api/atom_api_protocol.cc | 361 +----------------- atom/browser/api/atom_api_protocol.h | 118 +++--- atom/browser/api/lib/protocol.coffee | 58 --- atom/browser/atom_browser_client.cc | 2 +- atom/browser/atom_browser_context.cc | 35 +- atom/browser/lib/chrome-extension.coffee | 14 +- atom/browser/net/adapter_request_job.cc | 148 ------- atom/browser/net/adapter_request_job.h | 88 ----- .../net/atom_url_request_job_factory.cc | 19 +- .../net/atom_url_request_job_factory.h | 11 +- atom/browser/net/js_asker.cc | 106 +++++ atom/browser/net/js_asker.h | 85 +++++ atom/browser/net/url_request_string_job.cc | 26 +- atom/browser/net/url_request_string_job.h | 11 +- filenames.gypi | 4 +- vendor/brightray | 2 +- 16 files changed, 345 insertions(+), 743 deletions(-) delete mode 100644 atom/browser/net/adapter_request_job.cc delete mode 100644 atom/browser/net/adapter_request_job.h create mode 100644 atom/browser/net/js_asker.cc create mode 100644 atom/browser/net/js_asker.h diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index d7d308b306e..18a3ccca57e 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -7,15 +7,9 @@ #include "atom/browser/atom_browser_client.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/api/atom_api_session.h" -#include "atom/browser/net/adapter_request_job.h" -#include "atom/browser/net/atom_url_request_job_factory.h" +#include "atom/browser/net/url_request_string_job.h" #include "atom/common/native_mate_converters/callback.h" -#include "atom/common/native_mate_converters/file_path_converter.h" -#include "atom/common/native_mate_converters/gurl_converter.h" -#include "content/public/browser/browser_thread.h" #include "native_mate/dictionary.h" -#include "net/url_request/url_request_context.h" #include "atom/common/node_includes.h" @@ -41,230 +35,18 @@ namespace atom { namespace api { -namespace { - -typedef net::URLRequestJobFactory::ProtocolHandler ProtocolHandler; - -scoped_refptr BufferToRefCountedBytes( - v8::Local buf) { - scoped_refptr data(new base::RefCountedBytes); - auto start = reinterpret_cast(node::Buffer::Data(buf)); - data->data().assign(start, start + node::Buffer::Length(buf)); - return data; -} - -class CustomProtocolRequestJob : public AdapterRequestJob { - public: - CustomProtocolRequestJob(Protocol* registry, - ProtocolHandler* protocol_handler, - net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : AdapterRequestJob(protocol_handler, request, network_delegate), - registry_(registry) { - } - - void GetJobTypeInUI(const Protocol::JsProtocolHandler& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - v8::Locker locker(registry_->isolate()); - v8::HandleScope handle_scope(registry_->isolate()); - - // Call the JS handler. - v8::Local result = callback.Run(request()); - - // Determine the type of the job we are going to create. - if (result->IsString()) { - std::string data = mate::V8ToString(result); - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateStringJobAndStart, - GetWeakPtr(), "text/plain", "UTF-8", data)); - return; - } else if (result->IsObject()) { - v8::Local obj = result->ToObject(); - mate::Dictionary dict(registry_->isolate(), obj); - std::string name = mate::V8ToString(obj->GetConstructorName()); - if (name == "RequestStringJob") { - std::string mime_type, charset, data; - dict.Get("mimeType", &mime_type); - dict.Get("charset", &charset); - dict.Get("data", &data); - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateStringJobAndStart, - GetWeakPtr(), mime_type, charset, data)); - return; - } else if (name == "RequestBufferJob") { - std::string mime_type, encoding; - v8::Local buffer; - dict.Get("mimeType", &mime_type); - dict.Get("encoding", &encoding); - dict.Get("data", &buffer); - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateBufferJobAndStart, - GetWeakPtr(), mime_type, encoding, - BufferToRefCountedBytes(buffer))); - return; - } else if (name == "RequestFileJob") { - base::FilePath path; - dict.Get("path", &path); - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateFileJobAndStart, - GetWeakPtr(), path)); - return; - } else if (name == "RequestErrorJob") { - int error = net::ERR_NOT_IMPLEMENTED; - dict.Get("error", &error); - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateErrorJobAndStart, - GetWeakPtr(), error)); - return; - } else if (name == "RequestHttpJob") { - GURL url; - std::string method, referrer; - dict.Get("url", &url); - dict.Get("method", &method); - dict.Get("referrer", &referrer); - - v8::Local value; - mate::Handle session; - scoped_refptr request_context_getter; - // "session" null -> pass nullptr; - // "session" a Session object -> use passed session. - // "session" undefined -> use current session; - if (dict.Get("session", &session)) - request_context_getter = - session->browser_context()->GetRequestContext(); - else if (dict.Get("session", &value) && value->IsNull()) - request_context_getter = nullptr; - else - request_context_getter = registry_->request_context_getter(); - - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateHttpJobAndStart, GetWeakPtr(), - request_context_getter, url, method, referrer)); - return; - } - } - - // Try the default protocol handler if we have. - if (default_protocol_handler()) { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateJobFromProtocolHandlerAndStart, - GetWeakPtr())); - return; - } - - // Fallback to the not implemented error. - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateErrorJobAndStart, - GetWeakPtr(), net::ERR_NOT_IMPLEMENTED)); - } - - // AdapterRequestJob: - void GetJobType() override { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&CustomProtocolRequestJob::GetJobTypeInUI, - base::Unretained(this), - registry_->GetProtocolHandler(request()->url().scheme()))); - } - - private: - Protocol* registry_; // Weak, the Protocol class is expected to live forever. -}; - -// Always return the same CustomProtocolRequestJob for all requests, because -// the content API needs the ProtocolHandler to return a job immediately, and -// getting the real job from the JS requires asynchronous calls, so we have -// to create an adapter job first. -// Users can also pass an extra ProtocolHandler as the fallback one when -// registered handler doesn't want to deal with the request. -class CustomProtocolHandler : public ProtocolHandler { - public: - CustomProtocolHandler(api::Protocol* registry, - ProtocolHandler* protocol_handler = NULL) - : registry_(registry), protocol_handler_(protocol_handler) { - } - - net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - return new CustomProtocolRequestJob(registry_, protocol_handler_.get(), - request, network_delegate); - } - - ProtocolHandler* ReleaseDefaultProtocolHandler() { - return protocol_handler_.release(); - } - - ProtocolHandler* original_handler() { return protocol_handler_.get(); } - - private: - Protocol* registry_; // Weak, the Protocol class is expected to live forever. - scoped_ptr protocol_handler_; - - DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); -}; - -std::string ConvertErrorCode(int error_code) { - switch (error_code) { - case Protocol::ERR_SCHEME_REGISTERED: - return "The Scheme is already registered"; - case Protocol::ERR_SCHEME_UNREGISTERED: - return "The Scheme has not been registered"; - case Protocol::ERR_SCHEME_INTERCEPTED: - return "There is no protocol handler to intercept"; - case Protocol::ERR_SCHEME_UNINTERCEPTED: - return "The protocol is not intercepted"; - case Protocol::ERR_NO_SCHEME: - return "The Scheme does not exist."; - case Protocol::ERR_SCHEME: - return "Cannot intercept custom protocols"; - default: - NOTREACHED(); - return std::string(); - } -} - -} // namespace - Protocol::Protocol(AtomBrowserContext* browser_context) : request_context_getter_(browser_context->GetRequestContext()), job_factory_(browser_context->job_factory()) { CHECK(job_factory_); } -Protocol::JsProtocolHandler Protocol::GetProtocolHandler( - const std::string& scheme) { - return protocol_handlers_[scheme]; -} - -void Protocol::OnIOActionCompleted(const JsCompletionCallback& callback, - int error) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - - if (error) { - callback.Run(v8::Exception::Error( - mate::StringToV8(isolate(), ConvertErrorCode(error)))); - return; - } - - callback.Run(v8::Null(isolate())); -} - mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) - .SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol) - .SetMethod("_registerProtocol", &Protocol::RegisterProtocol) - .SetMethod("_unregisterProtocol", &Protocol::UnregisterProtocol) - .SetMethod("_interceptProtocol", &Protocol::InterceptProtocol) - .SetMethod("_uninterceptProtocol", &Protocol::UninterceptProtocol); + .SetMethod("registerStringProtocol", + &Protocol::RegisterProtocol); } void Protocol::RegisterStandardSchemes( @@ -272,131 +54,28 @@ void Protocol::RegisterStandardSchemes( atom::AtomBrowserClient::SetCustomSchemes(schemes); } -void Protocol::IsHandledProtocol(const std::string& scheme, - const net::CompletionCallback& callback) { - BrowserThread::PostTaskAndReplyWithResult(BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequestJobFactory::IsHandledProtocol, - base::Unretained(job_factory_), scheme), - callback); -} +void Protocol::OnIOCompleted( + const CompletionCallback& callback, ProtocolError error) { + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); -void Protocol::RegisterProtocol(v8::Isolate* isolate, - const std::string& scheme, - const JsProtocolHandler& handler, - const JsCompletionCallback& callback) { - BrowserThread::PostTaskAndReplyWithResult(BrowserThread::IO, FROM_HERE, - base::Bind(&Protocol::RegisterProtocolInIO, - base::Unretained(this), scheme, handler), - base::Bind(&Protocol::OnIOActionCompleted, - base::Unretained(this), callback)); -} - -void Protocol::UnregisterProtocol(v8::Isolate* isolate, - const std::string& scheme, - const JsCompletionCallback& callback) { - BrowserThread::PostTaskAndReplyWithResult(BrowserThread::IO, FROM_HERE, - base::Bind(&Protocol::UnregisterProtocolInIO, - base::Unretained(this), scheme), - base::Bind(&Protocol::OnIOActionCompleted, - base::Unretained(this), callback)); -} - -void Protocol::InterceptProtocol(v8::Isolate* isolate, - const std::string& scheme, - const JsProtocolHandler& handler, - const JsCompletionCallback& callback) { - BrowserThread::PostTaskAndReplyWithResult(BrowserThread::IO, FROM_HERE, - base::Bind(&Protocol::InterceptProtocolInIO, - base::Unretained(this), scheme, handler), - base::Bind(&Protocol::OnIOActionCompleted, - base::Unretained(this), callback)); -} - -void Protocol::UninterceptProtocol(v8::Isolate* isolate, - const std::string& scheme, - const JsCompletionCallback& callback) { - BrowserThread::PostTaskAndReplyWithResult(BrowserThread::IO, FROM_HERE, - base::Bind(&Protocol::UninterceptProtocolInIO, - base::Unretained(this), scheme), - base::Bind(&Protocol::OnIOActionCompleted, - base::Unretained(this), callback)); -} - -int Protocol::RegisterProtocolInIO(const std::string& scheme, - const JsProtocolHandler& handler) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (ContainsKey(protocol_handlers_, scheme) || - job_factory_->IsHandledProtocol(scheme)) { - return ERR_SCHEME_REGISTERED; + if (error == PROTOCOL_OK) { + callback.Run(v8::Null(isolate())); + } else { + std::string str = ErrorCodeToString(error); + callback.Run(v8::Exception::Error(mate::StringToV8(isolate(), str))); } - - protocol_handlers_[scheme] = handler; - job_factory_->SetProtocolHandler(scheme, new CustomProtocolHandler(this)); - - return OK; } -int Protocol::UnregisterProtocolInIO(const std::string& scheme) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme)); - if (it == protocol_handlers_.end()) { - return ERR_SCHEME_UNREGISTERED; +std::string Protocol::ErrorCodeToString(ProtocolError error) { + switch (error) { + case PROTOCOL_FAIL: return "Failed to manipulate protocol factory"; + case PROTOCOL_REGISTERED: return "The scheme has been registred"; + case PROTOCOL_NOT_REGISTERED: return "The scheme has not been registred"; + case PROTOCOL_INTERCEPTED: return "The scheme has been intercepted"; + case PROTOCOL_NOT_INTERCEPTED: return "The scheme has not been intercepted"; + default: return "Unexpected error"; } - - protocol_handlers_.erase(it); - job_factory_->SetProtocolHandler(scheme, NULL); - - return OK; -} - -int Protocol::InterceptProtocolInIO(const std::string& scheme, - const JsProtocolHandler& handler) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // Force the request context to initialize, otherwise we might have nothing - // to intercept. - request_context_getter_->GetURLRequestContext(); - - if (!job_factory_->HasProtocolHandler(scheme)) - return ERR_NO_SCHEME; - - if (ContainsKey(protocol_handlers_, scheme)) - return ERR_SCHEME; - - protocol_handlers_[scheme] = handler; - ProtocolHandler* original_handler = job_factory_->GetProtocolHandler(scheme); - if (original_handler == nullptr) { - return ERR_SCHEME_INTERCEPTED; - } - - job_factory_->ReplaceProtocol( - scheme, new CustomProtocolHandler(this, original_handler)); - - return OK; -} - -int Protocol::UninterceptProtocolInIO(const std::string& scheme) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme)); - if (it == protocol_handlers_.end()) - return ERR_SCHEME_UNREGISTERED; - - protocol_handlers_.erase(it); - CustomProtocolHandler* handler = static_cast( - job_factory_->GetProtocolHandler(scheme)); - if (handler->original_handler() == nullptr) { - return ERR_SCHEME_UNINTERCEPTED; - } - - // Reset the protocol handler to the orignal one and delete current protocol - // handler. - ProtocolHandler* original_handler = handler->ReleaseDefaultProtocolHandler(); - delete job_factory_->ReplaceProtocol(scheme, original_handler); - - return OK; } // static diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 4dec17a7434..54dac9b13b9 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -9,10 +9,11 @@ #include #include -#include "atom/browser/api/event_emitter.h" +#include "atom/browser/net/atom_url_request_job_factory.h" #include "base/callback.h" +#include "content/public/browser/browser_thread.h" #include "native_mate/handle.h" -#include "net/base/completion_callback.h" +#include "native_mate/wrappable.h" namespace net { class URLRequest; @@ -26,31 +27,15 @@ class AtomURLRequestJobFactory; namespace api { -class Protocol : public mate::EventEmitter { +class Protocol : public mate::Wrappable { public: - using JsProtocolHandler = - base::Callback(const net::URLRequest*)>; - using JsCompletionCallback = base::Callback)>; - - enum { - OK = 0, - ERR_SCHEME_REGISTERED, - ERR_SCHEME_UNREGISTERED, - ERR_SCHEME_INTERCEPTED, - ERR_SCHEME_UNINTERCEPTED, - ERR_NO_SCHEME, - ERR_SCHEME - }; + using Handler = + base::Callback)>; + using CompletionCallback = base::Callback)>; static mate::Handle Create( v8::Isolate* isolate, AtomBrowserContext* browser_context); - JsProtocolHandler GetProtocolHandler(const std::string& scheme); - - net::URLRequestContextGetter* request_context_getter() { - return request_context_getter_.get(); - } - protected: explicit Protocol(AtomBrowserContext* browser_context); @@ -59,48 +44,77 @@ class Protocol : public mate::EventEmitter { v8::Isolate* isolate); private: - typedef std::map ProtocolHandlersMap; + // Possible errors. + enum ProtocolError { + PROTOCOL_OK, // no error + PROTOCOL_FAIL, // operation failed, should never occur + PROTOCOL_REGISTERED, + PROTOCOL_NOT_REGISTERED, + PROTOCOL_INTERCEPTED, + PROTOCOL_NOT_INTERCEPTED, + }; - // Callback called after performing action on IO thread. - void OnIOActionCompleted(const JsCompletionCallback& callback, - int error); + // The protocol handler that will create a protocol handler for certain + // request job. + template + class CustomProtocolHandler + : public net::URLRequestJobFactory::ProtocolHandler { + public: + CustomProtocolHandler(v8::Isolate* isolate, const Handler& handler) + : isolate_(isolate), handler_(handler) {} + ~CustomProtocolHandler() override {} + + net::URLRequestJob* MaybeCreateJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + return new RequestJob(request, network_delegate, isolate_, handler_); + } + + private: + v8::Isolate* isolate_; + Protocol::Handler handler_; + + DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); + }; // Register schemes to standard scheme list. void RegisterStandardSchemes(const std::vector& schemes); - // Returns whether a scheme has been registered. - void IsHandledProtocol(const std::string& scheme, - const net::CompletionCallback& callback); - - // Register/unregister an networking |scheme| which would be handled by - // |callback|. + // Register the protocol with certain request job. + template void RegisterProtocol(v8::Isolate* isolate, const std::string& scheme, - const JsProtocolHandler& handler, - const JsCompletionCallback& callback); - void UnregisterProtocol(v8::Isolate* isolate, const std::string& scheme, - const JsCompletionCallback& callback); + const Handler& handler, + const CompletionCallback& callback) { + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&Protocol::RegisterProtocolInIO, + base::Unretained(this), scheme, handler), + base::Bind(&Protocol::OnIOCompleted, + base::Unretained(this), callback)); + } + template + ProtocolError RegisterProtocolInIO(const std::string& scheme, + const Handler& handler) { + if (job_factory_->IsHandledProtocol(scheme)) + return PROTOCOL_REGISTERED; + scoped_ptr> protocol_handler( + new CustomProtocolHandler(isolate(), handler)); + if (job_factory_->SetProtocolHandler(scheme, protocol_handler.Pass())) + return PROTOCOL_OK; + else + return PROTOCOL_FAIL; + } - // Intercept/unintercept an existing protocol handler. - void InterceptProtocol(v8::Isolate* isolate, - const std::string& scheme, - const JsProtocolHandler& handler, - const JsCompletionCallback& callback); - void UninterceptProtocol(v8::Isolate* isolate, const std::string& scheme, - const JsCompletionCallback& callback); + // Convert error code to JS exception and call the callback. + void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); - // The networking related operations have to be done in IO thread. - int RegisterProtocolInIO(const std::string& scheme, - const JsProtocolHandler& handler); - int UnregisterProtocolInIO(const std::string& scheme); - int InterceptProtocolInIO(const std::string& scheme, - const JsProtocolHandler& handler); - int UninterceptProtocolInIO(const std::string& scheme); + // Convert error code to string. + std::string ErrorCodeToString(ProtocolError error); scoped_refptr request_context_getter_; - AtomURLRequestJobFactory* job_factory_; - ProtocolHandlersMap protocol_handlers_; + AtomURLRequestJobFactory* job_factory_; // weak ref. DISALLOW_COPY_AND_ASSIGN(Protocol); }; diff --git a/atom/browser/api/lib/protocol.coffee b/atom/browser/api/lib/protocol.coffee index 4a661523509..4a45c702507 100644 --- a/atom/browser/api/lib/protocol.coffee +++ b/atom/browser/api/lib/protocol.coffee @@ -2,63 +2,5 @@ app = require 'app' throw new Error('Can not initialize protocol module before app is ready') unless app.isReady() protocol = process.atomBinding('protocol').protocol -EventEmitter = require('events').EventEmitter - -protocol.__proto__ = EventEmitter.prototype - -GetWrappedCallback = (scheme, callback, notification) -> - wrappedCallback = (error) -> - if not callback? - if error - throw error - else - protocol.emit notification, scheme - else - callback error, scheme - -# Compatibility with old api. -protocol.registerProtocol = (scheme, handler, callback) -> - protocol._registerProtocol scheme, handler, GetWrappedCallback(scheme, callback, 'registered') - -protocol.unregisterProtocol = (scheme, callback) -> - protocol._unregisterProtocol scheme, GetWrappedCallback(scheme, callback, 'unregistered') - -protocol.interceptProtocol = (scheme, handler, callback) -> - protocol._interceptProtocol scheme, handler, GetWrappedCallback(scheme, callback, 'intercepted') - -protocol.uninterceptProtocol = (scheme, callback) -> - protocol._uninterceptProtocol scheme, GetWrappedCallback(scheme, callback, 'unintercepted') - -protocol.RequestStringJob = -class RequestStringJob - constructor: ({mimeType, charset, data}) -> - if typeof data isnt 'string' and not data instanceof Buffer - throw new TypeError('Data should be string or Buffer') - - @mimeType = mimeType ? 'text/plain' - @charset = charset ? 'UTF-8' - @data = String data - -protocol.RequestBufferJob = -class RequestBufferJob - constructor: ({mimeType, encoding, data}) -> - if not data instanceof Buffer - throw new TypeError('Data should be Buffer') - - @mimeType = mimeType ? 'application/octet-stream' - @encoding = encoding ? 'utf8' - @data = new Buffer(data) - -protocol.RequestFileJob = -class RequestFileJob - constructor: (@path) -> - -protocol.RequestErrorJob = -class RequestErrorJob - constructor: (@error) -> - -protocol.RequestHttpJob = -class RequestHttpJob - constructor: ({@session, @url, @method, @referrer}) -> module.exports = protocol diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index f116af0a667..8db71fd3030 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -70,7 +70,7 @@ ProcessOwner GetProcessOwner(int process_id, // First search for NativeWindow. *window = NativeWindow::FromWebContents(web_contents); - if (window) + if (*window) return OWNER_NATIVE_WINDOW; // Then search for guest WebContents. diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index f04fbca747e..583a6324a8f 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -85,32 +85,37 @@ net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory( content::URLRequestInterceptorScopedVector* interceptors) { scoped_ptr job_factory(job_factory_); - for (content::ProtocolHandlerMap::iterator it = handlers->begin(); - it != handlers->end(); ++it) - job_factory->SetProtocolHandler(it->first, it->second.release()); + for (auto& it : *handlers) { + job_factory->SetProtocolHandler(it.first, + make_scoped_ptr(it.second.release())); + } handlers->clear(); job_factory->SetProtocolHandler( - url::kDataScheme, new net::DataProtocolHandler); + url::kDataScheme, make_scoped_ptr(new net::DataProtocolHandler)); job_factory->SetProtocolHandler( - url::kFileScheme, new asar::AsarProtocolHandler( + url::kFileScheme, make_scoped_ptr(new asar::AsarProtocolHandler( BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)))); job_factory->SetProtocolHandler( - url::kHttpScheme, new HttpProtocolHandler(url::kHttpScheme)); + url::kHttpScheme, + make_scoped_ptr(new HttpProtocolHandler(url::kHttpScheme))); job_factory->SetProtocolHandler( - url::kHttpsScheme, new HttpProtocolHandler(url::kHttpsScheme)); + url::kHttpsScheme, + make_scoped_ptr(new HttpProtocolHandler(url::kHttpsScheme))); job_factory->SetProtocolHandler( - url::kWsScheme, new HttpProtocolHandler(url::kWsScheme)); + url::kWsScheme, + make_scoped_ptr(new HttpProtocolHandler(url::kWsScheme))); job_factory->SetProtocolHandler( - url::kWssScheme, new HttpProtocolHandler(url::kWssScheme)); + url::kWssScheme, + make_scoped_ptr(new HttpProtocolHandler(url::kWssScheme))); - auto host_resolver = url_request_context_getter() - ->GetURLRequestContext() - ->host_resolver(); + auto host_resolver = + url_request_context_getter()->GetURLRequestContext()->host_resolver(); job_factory->SetProtocolHandler( - url::kFtpScheme, new net::FtpProtocolHandler( - new net::FtpNetworkLayer(host_resolver))); + url::kFtpScheme, + make_scoped_ptr(new net::FtpProtocolHandler( + new net::FtpNetworkLayer(host_resolver)))); // Set up interceptors in the reverse order. scoped_ptr top_job_factory = job_factory.Pass(); diff --git a/atom/browser/lib/chrome-extension.coffee b/atom/browser/lib/chrome-extension.coffee index 884a9e25d6e..c29df5d96f6 100644 --- a/atom/browser/lib/chrome-extension.coffee +++ b/atom/browser/lib/chrome-extension.coffee @@ -64,14 +64,14 @@ app.once 'ready', -> catch e # The chrome-extension: can map a extension URL request to real file path. - protocol.registerProtocol 'chrome-extension', (request) -> - parsed = url.parse request.url - return unless parsed.hostname and parsed.path? - return unless /extension-\d+/.test parsed.hostname + # protocol.registerProtocol 'chrome-extension', (request) -> + # parsed = url.parse request.url + # return unless parsed.hostname and parsed.path? + # return unless /extension-\d+/.test parsed.hostname - directory = getPathForHost parsed.hostname - return unless directory? - return new protocol.RequestFileJob(path.join(directory, parsed.path)) + # directory = getPathForHost parsed.hostname + # return unless directory? + # return new protocol.RequestFileJob(path.join(directory, parsed.path)) BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) -> @devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});" diff --git a/atom/browser/net/adapter_request_job.cc b/atom/browser/net/adapter_request_job.cc deleted file mode 100644 index ca7dcf2e566..00000000000 --- a/atom/browser/net/adapter_request_job.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/net/adapter_request_job.h" - -#include "base/threading/sequenced_worker_pool.h" -#include "atom/browser/net/url_request_buffer_job.h" -#include "atom/browser/net/url_request_fetch_job.h" -#include "atom/browser/net/url_request_string_job.h" -#include "atom/browser/net/asar/url_request_asar_job.h" -#include "atom/common/asar/asar_util.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/net_errors.h" -#include "net/url_request/url_request_error_job.h" -#include "net/url_request/url_request_file_job.h" - -namespace atom { - -AdapterRequestJob::AdapterRequestJob(ProtocolHandler* protocol_handler, - net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : URLRequestJob(request, network_delegate), - protocol_handler_(protocol_handler), - weak_factory_(this) { -} - -void AdapterRequestJob::Start() { - DCHECK(!real_job_.get()); - GetJobType(); -} - -void AdapterRequestJob::Kill() { - if (real_job_.get()) // Kill could happen when real_job_ is created. - real_job_->Kill(); -} - -bool AdapterRequestJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int *bytes_read) { - DCHECK(!real_job_.get()); - // Read post-filtered data if available. - if (real_job_->HasFilter()) - return real_job_->Read(buf, buf_size, bytes_read); - else - return real_job_->ReadRawData(buf, buf_size, bytes_read); -} - -bool AdapterRequestJob::IsRedirectResponse(GURL* location, - int* http_status_code) { - DCHECK(!real_job_.get()); - return real_job_->IsRedirectResponse(location, http_status_code); -} - -net::Filter* AdapterRequestJob::SetupFilter() const { - DCHECK(!real_job_.get()); - return real_job_->SetupFilter(); -} - -bool AdapterRequestJob::GetMimeType(std::string* mime_type) const { - DCHECK(!real_job_.get()); - return real_job_->GetMimeType(mime_type); -} - -bool AdapterRequestJob::GetCharset(std::string* charset) { - DCHECK(!real_job_.get()); - return real_job_->GetCharset(charset); -} - -void AdapterRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { - real_job_->GetResponseInfo(info); -} - -int AdapterRequestJob::GetResponseCode() const { - return real_job_->GetResponseCode(); -} - -void AdapterRequestJob::GetLoadTimingInfo( - net::LoadTimingInfo* load_timing_info) const { - real_job_->GetLoadTimingInfo(load_timing_info); -} - -base::WeakPtr AdapterRequestJob::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void AdapterRequestJob::CreateErrorJobAndStart(int error_code) { - real_job_ = new net::URLRequestErrorJob( - request(), network_delegate(), error_code); - real_job_->Start(); -} - -void AdapterRequestJob::CreateStringJobAndStart(const std::string& mime_type, - const std::string& charset, - const std::string& data) { - real_job_ = new URLRequestStringJob( - request(), network_delegate(), mime_type, charset, data); - real_job_->Start(); -} - -void AdapterRequestJob::CreateBufferJobAndStart( - const std::string& mime_type, - const std::string& charset, - scoped_refptr data) { - real_job_ = new URLRequestBufferJob( - request(), network_delegate(), mime_type, charset, data); - real_job_->Start(); -} - -void AdapterRequestJob::CreateFileJobAndStart(const base::FilePath& path) { - real_job_ = asar::CreateJobFromPath( - path, - request(), - network_delegate(), - content::BrowserThread::GetBlockingPool()-> - GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); - real_job_->Start(); -} - -void AdapterRequestJob::CreateHttpJobAndStart( - scoped_refptr request_context_getter, - const GURL& url, - const std::string& method, - const std::string& referrer) { - if (!url.is_valid()) { - CreateErrorJobAndStart(net::ERR_INVALID_URL); - return; - } - - real_job_ = new URLRequestFetchJob(request_context_getter, request(), - network_delegate(), url, method, referrer); - real_job_->Start(); -} - -void AdapterRequestJob::CreateJobFromProtocolHandlerAndStart() { - real_job_ = protocol_handler_->MaybeCreateJob(request(), - network_delegate()); - if (!real_job_.get()) { - CreateErrorJobAndStart(net::ERR_NOT_IMPLEMENTED); - } else { - // Copy headers from original request. - real_job_->SetExtraRequestHeaders(request()->extra_request_headers()); - real_job_->Start(); - } -} - -} // namespace atom diff --git a/atom/browser/net/adapter_request_job.h b/atom/browser/net/adapter_request_job.h deleted file mode 100644 index afb9d5f55d0..00000000000 --- a/atom/browser/net/adapter_request_job.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_NET_ADAPTER_REQUEST_JOB_H_ -#define ATOM_BROWSER_NET_ADAPTER_REQUEST_JOB_H_ - -#include - -#include "base/memory/ref_counted_memory.h" -#include "base/memory/weak_ptr.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_job.h" -#include "net/url_request/url_request_job_factory.h" -#include "v8/include/v8.h" - -namespace base { -class FilePath; -} - -namespace atom { - -class AtomBrowserContext; - -// Ask JS which type of job it wants, and then delegate corresponding methods. -class AdapterRequestJob : public net::URLRequestJob { - public: - typedef net::URLRequestJobFactory::ProtocolHandler ProtocolHandler; - - AdapterRequestJob(ProtocolHandler* protocol_handler, - net::URLRequest* request, - net::NetworkDelegate* network_delegate); - - public: - // net::URLRequestJob: - void Start() override; - void Kill() override; - bool ReadRawData(net::IOBuffer* buf, - int buf_size, - int *bytes_read) override; - bool IsRedirectResponse(GURL* location, - int* http_status_code) override; - net::Filter* SetupFilter() const override; - bool GetMimeType(std::string* mime_type) const override; - bool GetCharset(std::string* charset) override; - void GetResponseInfo(net::HttpResponseInfo* info) override; - int GetResponseCode() const override; - void GetLoadTimingInfo( - net::LoadTimingInfo* load_timing_info) const override; - - base::WeakPtr GetWeakPtr(); - - ProtocolHandler* default_protocol_handler() { return protocol_handler_; } - - // Override this function to determine which job should be started. - virtual void GetJobType() = 0; - - void CreateErrorJobAndStart(int error_code); - void CreateStringJobAndStart(const std::string& mime_type, - const std::string& charset, - const std::string& data); - void CreateBufferJobAndStart(const std::string& mime_type, - const std::string& charset, - scoped_refptr data); - void CreateFileJobAndStart(const base::FilePath& path); - void CreateHttpJobAndStart( - scoped_refptr request_context_getter, - const GURL& url, - const std::string& method, - const std::string& referrer); - void CreateJobFromProtocolHandlerAndStart(); - - private: - // The delegated request job. - scoped_refptr real_job_; - - // Default protocol handler. - ProtocolHandler* protocol_handler_; - - base::WeakPtrFactory weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(AdapterRequestJob); -}; - -} // namespace atom - -#endif // ATOM_BROWSER_NET_ADAPTER_REQUEST_JOB_H_ diff --git a/atom/browser/net/atom_url_request_job_factory.cc b/atom/browser/net/atom_url_request_job_factory.cc index 00942b2ad05..dbd8b4160cf 100644 --- a/atom/browser/net/atom_url_request_job_factory.cc +++ b/atom/browser/net/atom_url_request_job_factory.cc @@ -23,10 +23,7 @@ AtomURLRequestJobFactory::~AtomURLRequestJobFactory() { } bool AtomURLRequestJobFactory::SetProtocolHandler( - const std::string& scheme, - ProtocolHandler* protocol_handler) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - + const std::string& scheme, scoped_ptr protocol_handler) { if (!protocol_handler) { ProtocolHandlerMap::iterator it = protocol_handler_map_.find(scheme); if (it == protocol_handler_map_.end()) @@ -39,21 +36,17 @@ bool AtomURLRequestJobFactory::SetProtocolHandler( if (ContainsKey(protocol_handler_map_, scheme)) return false; - protocol_handler_map_[scheme] = protocol_handler; + protocol_handler_map_[scheme] = protocol_handler.release(); return true; } -ProtocolHandler* AtomURLRequestJobFactory::ReplaceProtocol( - const std::string& scheme, - ProtocolHandler* protocol_handler) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(protocol_handler); - +scoped_ptr AtomURLRequestJobFactory::ReplaceProtocol( + const std::string& scheme, scoped_ptr protocol_handler) { if (!ContainsKey(protocol_handler_map_, scheme)) return nullptr; ProtocolHandler* original_protocol_handler = protocol_handler_map_[scheme]; - protocol_handler_map_[scheme] = protocol_handler; - return original_protocol_handler; + protocol_handler_map_[scheme] = protocol_handler.release(); + return make_scoped_ptr(original_protocol_handler); } ProtocolHandler* AtomURLRequestJobFactory::GetProtocolHandler( diff --git a/atom/browser/net/atom_url_request_job_factory.h b/atom/browser/net/atom_url_request_job_factory.h index ce2a18a85e6..dde36225b7a 100644 --- a/atom/browser/net/atom_url_request_job_factory.h +++ b/atom/browser/net/atom_url_request_job_factory.h @@ -10,8 +10,7 @@ #include #include -#include "base/basictypes.h" -#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "net/url_request/url_request_job_factory.h" @@ -25,13 +24,13 @@ class AtomURLRequestJobFactory : public net::URLRequestJobFactory { // Sets the ProtocolHandler for a scheme. Returns true on success, false on // failure (a ProtocolHandler already exists for |scheme|). On success, // URLRequestJobFactory takes ownership of |protocol_handler|. - bool SetProtocolHandler(const std::string& scheme, - ProtocolHandler* protocol_handler); + bool SetProtocolHandler( + const std::string& scheme, scoped_ptr protocol_handler); // Intercepts the ProtocolHandler for a scheme. Returns the original protocol // handler on success, otherwise returns NULL. - ProtocolHandler* ReplaceProtocol(const std::string& scheme, - ProtocolHandler* protocol_handler); + scoped_ptr ReplaceProtocol( + const std::string& scheme, scoped_ptr protocol_handler); // Returns the protocol handler registered with scheme. ProtocolHandler* GetProtocolHandler(const std::string& scheme) const; diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc new file mode 100644 index 00000000000..a24e9102179 --- /dev/null +++ b/atom/browser/net/js_asker.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/net/js_asker.h" + +#include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/v8_value_converter.h" +#include "native_mate/function_template.h" + +namespace atom { + +namespace internal { + +namespace { + +struct CallbackHolder { + ResponseCallback callback; +}; + +// Cached JavaScript version of |HandlerCallback|. +v8::Persistent g_handler_callback_; + +// Cached C++ version of |Function.prototype.bind|. +base::Callback( + v8::Local, v8::Local, v8::Local)> g_bind; + +// The callback which is passed to |handler|. +void HandlerCallback(v8::Local external, mate::Arguments* args) { + scoped_ptr holder( + static_cast(external->Value())); + CHECK(holder); + v8::Local value; + if (!args->GetNext(&value)) { + holder->callback.Run(false, nullptr); + return; + } + + V8ValueConverter converter; + v8::Local context = args->isolate()->GetCurrentContext(); + scoped_ptr options(converter.FromV8Value(value, context)); + holder->callback.Run(true, options.Pass()); +} + +// func.bind(...). +template +v8::Local BindFunctionWith(v8::Isolate* isolate, + v8::Local context, + v8::Local func, + ArgTypes... args) { + v8::MaybeLocal bind = func->Get(mate::StringToV8(isolate, "bind")); + CHECK(!bind.IsEmpty()); + v8::Local bind_func = + v8::Local::Cast(bind.ToLocalChecked()); + std::vector> converted = { + func, mate::ConvertToV8(isolate, args)..., + }; + return bind_func->Call( + context, func, converted.size(), &converted.front()).ToLocalChecked(); +} + +// Generate the callback that will be passed to |handler|. +v8::MaybeLocal GenerateCallback(v8::Isolate* isolate, + v8::Local context, + const ResponseCallback& callback) { + // The FunctionTemplate is cached. + if (g_handler_callback_.IsEmpty()) + g_handler_callback_.Reset( + isolate, + mate::CreateFunctionTemplate(isolate, base::Bind(&HandlerCallback))); + + v8::Local handler_callback = + v8::Local::New(isolate, g_handler_callback_); + CallbackHolder* holder = new CallbackHolder; + holder->callback = callback; + return BindFunctionWith(isolate, context, + handler_callback->GetFunction(), + v8::External::New(isolate, holder)); +} + +} // namespace + +void AskForOptions(v8::Isolate* isolate, + const JavaScriptHandler& handler, + net::URLRequest* request, + const ResponseCallback& callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Context::Scope context_scope(context); + // We don't convert the callback to C++ directly because creating + // FunctionTemplate will cause memory leak since V8 never releases it. So we + // have to create the function object in JavaScript to work around it. + v8::MaybeLocal wrapped_callback = GenerateCallback( + isolate, context, callback); + if (wrapped_callback.IsEmpty()) { + callback.Run(false, nullptr); + return; + } + handler.Run(request, wrapped_callback.ToLocalChecked()); +} + +} // namespace internal + +} // namespace atom diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h new file mode 100644 index 00000000000..a1bf972f63f --- /dev/null +++ b/atom/browser/net/js_asker.h @@ -0,0 +1,85 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_JS_ASKER_H_ +#define ATOM_BROWSER_NET_JS_ASKER_H_ + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request_job.h" +#include "v8/include/v8.h" + +namespace atom { + +using JavaScriptHandler = + base::Callback)>; + +namespace internal { + +using ResponseCallback = + base::Callback options)>; + +// Ask handler for options in UI thread. +void AskForOptions(v8::Isolate* isolate, + const JavaScriptHandler& handler, + net::URLRequest* request, + const ResponseCallback& callback); + +} // namespace internal + +template +class JsAsker : public RequestJob { + public: + JsAsker(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + v8::Isolate* isolate, + const JavaScriptHandler& handler) + : RequestJob(request, network_delegate), + isolate_(isolate), + handler_(handler), + weak_factory_(this) {} + + // Subclass should do initailze work here. + virtual void StartAsync(scoped_ptr options) { + RequestJob::Start(); + } + + private: + // RequestJob: + void Start() override { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&internal::AskForOptions, + isolate_, + handler_, + RequestJob::request(), + base::Bind(&JsAsker::OnResponse, + weak_factory_.GetWeakPtr()))); + } + + // Called when the JS handler has sent the response, we need to decide whether + // to start, or fail the job. + void OnResponse(bool success, scoped_ptr options) { + if (success) { + StartAsync(options.Pass()); + } else { + RequestJob::NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_NOT_IMPLEMENTED)); + } + } + + v8::Isolate* isolate_; + JavaScriptHandler handler_; + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(JsAsker); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_JS_ASKER_H_ diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index d0f205789a8..1afa95e5128 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -12,13 +12,25 @@ namespace atom { URLRequestStringJob::URLRequestStringJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const std::string& mime_type, - const std::string& charset, - const std::string& data) - : net::URLRequestSimpleJob(request, network_delegate), - mime_type_(mime_type), - charset_(charset), - data_(data) { + v8::Isolate* isolate, + const JavaScriptHandler& handler) + : JsAsker(request, network_delegate, isolate, + handler) { +} + +void URLRequestStringJob::StartAsync(scoped_ptr options) { + if (options) { + if (options->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict = + static_cast(options.get()); + dict->GetString("mimeType", &mime_type_); + dict->GetString("charset", &charset_); + dict->GetString("data", &data_); + } else if (options->IsType(base::Value::TYPE_STRING)) { + options->GetAsString(&data_); + } + } + net::URLRequestSimpleJob::Start(); } int URLRequestStringJob::GetData( diff --git a/atom/browser/net/url_request_string_job.h b/atom/browser/net/url_request_string_job.h index 7ad250466ab..7a2e23acab0 100644 --- a/atom/browser/net/url_request_string_job.h +++ b/atom/browser/net/url_request_string_job.h @@ -5,19 +5,22 @@ #ifndef ATOM_BROWSER_NET_URL_REQUEST_STRING_JOB_H_ #define ATOM_BROWSER_NET_URL_REQUEST_STRING_JOB_H_ +#include "atom/browser/net/js_asker.h" #include "net/url_request/url_request_simple_job.h" #include namespace atom { -class URLRequestStringJob : public net::URLRequestSimpleJob { +class URLRequestStringJob : public JsAsker { public: URLRequestStringJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const std::string& mime_type, - const std::string& charset, - const std::string& data); + v8::Isolate* isolate, + const JavaScriptHandler& handler); + + // JsAsker: + void StartAsync(scoped_ptr options) override; // URLRequestSimpleJob: int GetData(std::string* mime_type, diff --git a/filenames.gypi b/filenames.gypi index 40af1ebb1fe..2dc110ef859 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -146,8 +146,6 @@ 'atom/browser/native_window_mac.h', 'atom/browser/native_window_mac.mm', 'atom/browser/native_window_observer.h', - 'atom/browser/net/adapter_request_job.cc', - 'atom/browser/net/adapter_request_job.h', 'atom/browser/net/asar/asar_protocol_handler.cc', 'atom/browser/net/asar/asar_protocol_handler.h', 'atom/browser/net/asar/url_request_asar_job.cc', @@ -156,6 +154,8 @@ 'atom/browser/net/atom_url_request_job_factory.h', 'atom/browser/net/http_protocol_handler.cc', 'atom/browser/net/http_protocol_handler.h', + 'atom/browser/net/js_asker.cc', + 'atom/browser/net/js_asker.h', 'atom/browser/net/url_request_string_job.cc', 'atom/browser/net/url_request_string_job.h', 'atom/browser/net/url_request_buffer_job.cc', diff --git a/vendor/brightray b/vendor/brightray index 46b093d5147..cb8f80f473a 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 46b093d514750aee66092ec64defe7bd8e1bc74d +Subproject commit cb8f80f473a54fe1de72d478fd7809cf0c01fdb2 From ee51e37db7e1a0739d6bb2be463b4458b637e3c9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 13:43:27 +0800 Subject: [PATCH 25/55] Guard against callback being called twice --- atom/browser/net/js_asker.cc | 25 +++++++++++++++------- atom/browser/net/js_asker.h | 2 +- atom/browser/net/url_request_string_job.cc | 18 +++++++--------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index a24e9102179..96c6736150e 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -21,14 +21,21 @@ struct CallbackHolder { // Cached JavaScript version of |HandlerCallback|. v8::Persistent g_handler_callback_; -// Cached C++ version of |Function.prototype.bind|. -base::Callback( - v8::Local, v8::Local, v8::Local)> g_bind; - // The callback which is passed to |handler|. -void HandlerCallback(v8::Local external, mate::Arguments* args) { +void HandlerCallback(v8::Isolate* isolate, + v8::Local external, + v8::Local state, + mate::Arguments* args) { + // Check if the callback has already been called. + v8::Local called_symbol = mate::StringToSymbol(isolate, "called"); + if (state->Has(called_symbol)) + return; // no nothing + else + state->Set(called_symbol, v8::Boolean::New(isolate, true)); + + // If there is no argument passed then we failed. scoped_ptr holder( - static_cast(external->Value())); + static_cast(external->Value())); CHECK(holder); v8::Local value; if (!args->GetNext(&value)) { @@ -36,13 +43,14 @@ void HandlerCallback(v8::Local external, mate::Arguments* args) { return; } + // Pass whatever user passed to the actaul request job. V8ValueConverter converter; v8::Local context = args->isolate()->GetCurrentContext(); scoped_ptr options(converter.FromV8Value(value, context)); holder->callback.Run(true, options.Pass()); } -// func.bind(...). +// func.bind(func, ...). template v8::Local BindFunctionWith(v8::Isolate* isolate, v8::Local context, @@ -75,7 +83,8 @@ v8::MaybeLocal GenerateCallback(v8::Isolate* isolate, holder->callback = callback; return BindFunctionWith(isolate, context, handler_callback->GetFunction(), - v8::External::New(isolate, holder)); + v8::External::New(isolate, holder), + v8::Object::New(isolate)); } } // namespace diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index a1bf972f63f..97b384e213f 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -64,7 +64,7 @@ class JsAsker : public RequestJob { // Called when the JS handler has sent the response, we need to decide whether // to start, or fail the job. void OnResponse(bool success, scoped_ptr options) { - if (success) { + if (success && options) { StartAsync(options.Pass()); } else { RequestJob::NotifyStartError( diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index 1afa95e5128..eec8176d734 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -19,16 +19,14 @@ URLRequestStringJob::URLRequestStringJob(net::URLRequest* request, } void URLRequestStringJob::StartAsync(scoped_ptr options) { - if (options) { - if (options->IsType(base::Value::TYPE_DICTIONARY)) { - base::DictionaryValue* dict = - static_cast(options.get()); - dict->GetString("mimeType", &mime_type_); - dict->GetString("charset", &charset_); - dict->GetString("data", &data_); - } else if (options->IsType(base::Value::TYPE_STRING)) { - options->GetAsString(&data_); - } + if (options->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict = + static_cast(options.get()); + dict->GetString("mimeType", &mime_type_); + dict->GetString("charset", &charset_); + dict->GetString("data", &data_); + } else if (options->IsType(base::Value::TYPE_STRING)) { + options->GetAsString(&data_); } net::URLRequestSimpleJob::Start(); } From 337460cdc278afbb2753680cf49b8442892db4bf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 13:50:31 +0800 Subject: [PATCH 26/55] Enable return error for arbitray request job --- atom/browser/net/js_asker.cc | 12 ++++++++++++ atom/browser/net/js_asker.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index 96c6736150e..b53799b06fd 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -110,6 +110,18 @@ void AskForOptions(v8::Isolate* isolate, handler.Run(request, wrapped_callback.ToLocalChecked()); } +bool IsErrorOptions(base::Value* value, int* error) { + if (value->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict = static_cast(value); + if (dict->GetInteger("error", error)) + return true; + } else if (value->IsType(base::Value::TYPE_INTEGER)) { + if (value->GetAsInteger(error)) + return true; + } + return false; +} + } // namespace internal } // namespace atom diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 97b384e213f..0f5f05856cd 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -29,6 +29,9 @@ void AskForOptions(v8::Isolate* isolate, net::URLRequest* request, const ResponseCallback& callback); +// Test whether the |options| means an error. +bool IsErrorOptions(base::Value* value, int* error); + } // namespace internal template @@ -63,13 +66,13 @@ class JsAsker : public RequestJob { // Called when the JS handler has sent the response, we need to decide whether // to start, or fail the job. - void OnResponse(bool success, scoped_ptr options) { - if (success && options) { - StartAsync(options.Pass()); + void OnResponse(bool success, scoped_ptr value) { + int error = net::ERR_NOT_IMPLEMENTED; + if (success && value && !internal::IsErrorOptions(value.get(), &error)) { + StartAsync(value.Pass()); } else { RequestJob::NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_NOT_IMPLEMENTED)); + net::URLRequestStatus(net::URLRequestStatus::FAILED, error)); } } From d2681d2ba1b18c719fa606d19d77a16f1cd80577 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 15:18:31 +0800 Subject: [PATCH 27/55] Implement protocol.registerFileProtocol --- atom/browser/api/atom_api_protocol.cc | 5 +- atom/browser/lib/chrome-extension.coffee | 16 +- .../browser/net/asar/asar_protocol_handler.cc | 39 +-- atom/browser/net/asar/url_request_asar_job.cc | 271 +++++++++++++++--- atom/browser/net/asar/url_request_asar_job.h | 68 ++++- .../browser/net/url_request_async_asar_job.cc | 40 +++ atom/browser/net/url_request_async_asar_job.h | 30 ++ filenames.gypi | 2 + 8 files changed, 383 insertions(+), 88 deletions(-) create mode 100644 atom/browser/net/url_request_async_asar_job.cc create mode 100644 atom/browser/net/url_request_async_asar_job.h diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 18a3ccca57e..0bd6728b4cf 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -8,6 +8,7 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/net/url_request_string_job.h" +#include "atom/browser/net/url_request_async_asar_job.h" #include "atom/common/native_mate_converters/callback.h" #include "native_mate/dictionary.h" @@ -46,7 +47,9 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( return mate::ObjectTemplateBuilder(isolate) .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) .SetMethod("registerStringProtocol", - &Protocol::RegisterProtocol); + &Protocol::RegisterProtocol) + .SetMethod("registerFileProtocol", + &Protocol::RegisterProtocol); } void Protocol::RegisterStandardSchemes( diff --git a/atom/browser/lib/chrome-extension.coffee b/atom/browser/lib/chrome-extension.coffee index c29df5d96f6..ccb52d37a4b 100644 --- a/atom/browser/lib/chrome-extension.coffee +++ b/atom/browser/lib/chrome-extension.coffee @@ -64,14 +64,16 @@ app.once 'ready', -> catch e # The chrome-extension: can map a extension URL request to real file path. - # protocol.registerProtocol 'chrome-extension', (request) -> - # parsed = url.parse request.url - # return unless parsed.hostname and parsed.path? - # return unless /extension-\d+/.test parsed.hostname + chromeExtensionHandler = (request, callback) -> + parsed = url.parse request.url + return callback() unless parsed.hostname and parsed.path? + return callback() unless /extension-\d+/.test parsed.hostname - # directory = getPathForHost parsed.hostname - # return unless directory? - # return new protocol.RequestFileJob(path.join(directory, parsed.path)) + directory = getPathForHost parsed.hostname + return callback() unless directory? + callback path.join(directory, parsed.path) + protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, -> + console.error 'Unable to register chrome-extension protocol' BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) -> @devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});" diff --git a/atom/browser/net/asar/asar_protocol_handler.cc b/atom/browser/net/asar/asar_protocol_handler.cc index 6d2a2cd5bf0..324f8339c8c 100644 --- a/atom/browser/net/asar/asar_protocol_handler.cc +++ b/atom/browser/net/asar/asar_protocol_handler.cc @@ -5,45 +5,11 @@ #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/asar/url_request_asar_job.h" -#include "atom/common/asar/archive.h" -#include "atom/common/asar/asar_util.h" #include "net/base/filename_util.h" #include "net/base/net_errors.h" -#include "net/url_request/url_request_error_job.h" -#include "net/url_request/url_request_file_job.h" namespace asar { -// static -net::URLRequestJob* CreateJobFromPath( - const base::FilePath& full_path, - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const scoped_refptr file_task_runner) { - // Create asar:// job when the path contains "xxx.asar/", otherwise treat the - // URL request as file://. - base::FilePath asar_path, relative_path; - if (!GetAsarArchivePath(full_path, &asar_path, &relative_path)) - return new net::URLRequestFileJob(request, network_delegate, full_path, - file_task_runner); - - std::shared_ptr archive = GetOrCreateAsarArchive(asar_path); - Archive::FileInfo file_info; - if (!archive || !archive->GetFileInfo(relative_path, &file_info)) - return new net::URLRequestErrorJob(request, network_delegate, - net::ERR_FILE_NOT_FOUND); - - if (file_info.unpacked) { - base::FilePath real_path; - archive->CopyFileOut(relative_path, &real_path); - return new net::URLRequestFileJob(request, network_delegate, real_path, - file_task_runner); - } - - return new URLRequestAsarJob(request, network_delegate, archive, - relative_path, file_info, file_task_runner); -} - AsarProtocolHandler::AsarProtocolHandler( const scoped_refptr& file_task_runner) : file_task_runner_(file_task_runner) {} @@ -56,8 +22,9 @@ net::URLRequestJob* AsarProtocolHandler::MaybeCreateJob( net::NetworkDelegate* network_delegate) const { base::FilePath full_path; net::FileURLToFilePath(request->url(), &full_path); - return CreateJobFromPath(full_path, request, network_delegate, - file_task_runner_); + URLRequestAsarJob* job = new URLRequestAsarJob(request, network_delegate); + job->Initialize(file_task_runner_, full_path); + return job; } bool AsarProtocolHandler::IsSafeRedirectTarget(const GURL& location) const { diff --git a/atom/browser/net/asar/url_request_asar_job.cc b/atom/browser/net/asar/url_request_asar_job.cc index 477c6610b1b..33cb04c9ede 100644 --- a/atom/browser/net/asar/url_request_asar_job.cc +++ b/atom/browser/net/asar/url_request_asar_job.cc @@ -6,47 +6,126 @@ #include +#include "base/bind.h" +#include "base/files/file_util.h" +#include "base/strings/string_util.h" +#include "base/synchronization/lock.h" +#include "base/task_runner.h" +#include "atom/common/asar/archive.h" +#include "atom/common/asar/asar_util.h" #include "net/base/file_stream.h" +#include "net/base/filename_util.h" #include "net/base/io_buffer.h" +#include "net/base/load_flags.h" #include "net/base/mime_util.h" #include "net/base/net_errors.h" +#include "net/filter/filter.h" +#include "net/http/http_util.h" #include "net/url_request/url_request_status.h" +#if defined(OS_WIN) +#include "base/win/shortcut.h" +#endif + namespace asar { +URLRequestAsarJob::FileMetaInfo::FileMetaInfo() + : file_size(0), + mime_type_result(false), + file_exists(false), + is_directory(false) { +} + URLRequestAsarJob::URLRequestAsarJob( net::URLRequest* request, - net::NetworkDelegate* network_delegate, - std::shared_ptr archive, - const base::FilePath& file_path, - const Archive::FileInfo& file_info, - const scoped_refptr& file_task_runner) + net::NetworkDelegate* network_delegate) : net::URLRequestJob(request, network_delegate), - archive_(archive), - file_path_(file_path), - file_info_(file_info), - stream_(new net::FileStream(file_task_runner)), + type_(TYPE_ERROR), remaining_bytes_(0), - file_task_runner_(file_task_runner), weak_ptr_factory_(this) {} URLRequestAsarJob::~URLRequestAsarJob() {} -void URLRequestAsarJob::Start() { - remaining_bytes_ = static_cast(file_info_.size); +void URLRequestAsarJob::Initialize( + const scoped_refptr file_task_runner, + const base::FilePath& file_path) { + // Determine whether it is an asar file. + base::FilePath asar_path, relative_path; + if (!GetAsarArchivePath(file_path, &asar_path, &relative_path)) { + InitializeFileJob(file_task_runner, file_path); + return; + } - int flags = base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_ASYNC; - int rv = stream_->Open(archive_->path(), flags, - base::Bind(&URLRequestAsarJob::DidOpen, - weak_ptr_factory_.GetWeakPtr())); - if (rv != net::ERR_IO_PENDING) - DidOpen(rv); + std::shared_ptr archive = GetOrCreateAsarArchive(asar_path); + Archive::FileInfo file_info; + if (!archive || !archive->GetFileInfo(relative_path, &file_info)) { + type_ = TYPE_ERROR; + return; + } + + if (file_info.unpacked) { + base::FilePath real_path; + archive->CopyFileOut(relative_path, &real_path); + InitializeFileJob(file_task_runner, real_path); + return; + } + + InitializeAsarJob(file_task_runner, archive, relative_path, file_info); +} + +void URLRequestAsarJob::InitializeAsarJob( + const scoped_refptr file_task_runner, + std::shared_ptr archive, + const base::FilePath& file_path, + const Archive::FileInfo& file_info) { + type_ = TYPE_ASAR; + file_task_runner_ = file_task_runner; + stream_.reset(new net::FileStream(file_task_runner_)); + archive_ = archive; + file_path_ = file_path; + file_info_ = file_info; +} + +void URLRequestAsarJob::InitializeFileJob( + const scoped_refptr file_task_runner, + const base::FilePath& file_path) { + type_ = TYPE_FILE; + file_task_runner_ = file_task_runner; + stream_.reset(new net::FileStream(file_task_runner_)); + file_path_ = file_path; +} + +void URLRequestAsarJob::Start() { + if (type_ == TYPE_ASAR) { + remaining_bytes_ = static_cast(file_info_.size); + + int flags = base::File::FLAG_OPEN | + base::File::FLAG_READ | + base::File::FLAG_ASYNC; + int rv = stream_->Open(archive_->path(), flags, + base::Bind(&URLRequestAsarJob::DidOpen, + weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) + DidOpen(rv); + } else if (type_ == TYPE_FILE) { + FileMetaInfo* meta_info = new FileMetaInfo(); + file_task_runner_->PostTaskAndReply( + FROM_HERE, + base::Bind(&URLRequestAsarJob::FetchMetaInfo, file_path_, + base::Unretained(meta_info)), + base::Bind(&URLRequestAsarJob::DidFetchMetaInfo, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(meta_info))); + } else { + NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_FILE_NOT_FOUND)); + } } void URLRequestAsarJob::Kill() { + stream_.reset(); weak_ptr_factory_.InvalidateWeakPtrs(); + URLRequestJob::Kill(); } @@ -85,8 +164,97 @@ bool URLRequestAsarJob::ReadRawData(net::IOBuffer* dest, return false; } +bool URLRequestAsarJob::IsRedirectResponse(GURL* location, + int* http_status_code) { + if (type_ != TYPE_FILE) + return false; +#if defined(OS_WIN) + // Follow a Windows shortcut. + // We just resolve .lnk file, ignore others. + if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk")) + return false; + + base::FilePath new_path = file_path_; + bool resolved; + resolved = base::win::ResolveShortcut(new_path, &new_path, NULL); + + // If shortcut is not resolved succesfully, do not redirect. + if (!resolved) + return false; + + *location = net::FilePathToFileURL(new_path); + *http_status_code = 301; + return true; +#else + return false; +#endif +} + +net::Filter* URLRequestAsarJob::SetupFilter() const { + // Bug 9936 - .svgz files needs to be decompressed. + return LowerCaseEqualsASCII(file_path_.Extension(), ".svgz") + ? net::Filter::GZipFactory() : NULL; +} + bool URLRequestAsarJob::GetMimeType(std::string* mime_type) const { - return net::GetMimeTypeFromFile(file_path_, mime_type); + if (type_ == TYPE_ASAR) { + return net::GetMimeTypeFromFile(file_path_, mime_type); + } else { + if (meta_info_.mime_type_result) { + *mime_type = meta_info_.mime_type; + return true; + } + return false; + } +} + +void URLRequestAsarJob::SetExtraRequestHeaders( + const net::HttpRequestHeaders& headers) { + std::string range_header; + if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { + // We only care about "Range" header here. + std::vector ranges; + if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { + if (ranges.size() == 1) { + byte_range_ = ranges[0]; + } else { + NotifyDone(net::URLRequestStatus( + net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + } + } + } +} + +void URLRequestAsarJob::FetchMetaInfo(const base::FilePath& file_path, + FileMetaInfo* meta_info) { + base::File::Info file_info; + meta_info->file_exists = base::GetFileInfo(file_path, &file_info); + if (meta_info->file_exists) { + meta_info->file_size = file_info.size; + meta_info->is_directory = file_info.is_directory; + } + // On Windows GetMimeTypeFromFile() goes to the registry. Thus it should be + // done in WorkerPool. + meta_info->mime_type_result = + net::GetMimeTypeFromFile(file_path, &meta_info->mime_type); +} + +void URLRequestAsarJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) { + meta_info_ = *meta_info; + if (!meta_info_.file_exists || meta_info_.is_directory) { + DidOpen(net::ERR_FILE_NOT_FOUND); + return; + } + + int flags = base::File::FLAG_OPEN | + base::File::FLAG_READ | + base::File::FLAG_ASYNC; + int rv = stream_->Open(file_path_, flags, + base::Bind(&URLRequestAsarJob::DidOpen, + weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) + DidOpen(rv); } void URLRequestAsarJob::DidOpen(int result) { @@ -95,24 +263,59 @@ void URLRequestAsarJob::DidOpen(int result) { return; } - int rv = stream_->Seek(base::File::FROM_BEGIN, - file_info_.offset, - base::Bind(&URLRequestAsarJob::DidSeek, - weak_ptr_factory_.GetWeakPtr())); - if (rv != net::ERR_IO_PENDING) { - // stream_->Seek() failed, so pass an intentionally erroneous value - // into DidSeek(). - DidSeek(-1); + if (type_ == TYPE_ASAR) { + int rv = stream_->Seek(base::File::FROM_BEGIN, + file_info_.offset, + base::Bind(&URLRequestAsarJob::DidSeek, + weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) { + // stream_->Seek() failed, so pass an intentionally erroneous value + // into DidSeek(). + DidSeek(-1); + } + } else { + if (!byte_range_.ComputeBounds(meta_info_.file_size)) { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + return; + } + + remaining_bytes_ = byte_range_.last_byte_position() - + byte_range_.first_byte_position() + 1; + + if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) { + int rv = stream_->Seek(base::File::FROM_BEGIN, + byte_range_.first_byte_position(), + base::Bind(&URLRequestAsarJob::DidSeek, + weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) { + // stream_->Seek() failed, so pass an intentionally erroneous value + // into DidSeek(). + DidSeek(-1); + } + } else { + // We didn't need to call stream_->Seek() at all, so we pass to DidSeek() + // the value that would mean seek success. This way we skip the code + // handling seek failure. + DidSeek(byte_range_.first_byte_position()); + } } } void URLRequestAsarJob::DidSeek(int64 result) { - if (result != static_cast(file_info_.offset)) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); - return; + if (type_ == TYPE_ASAR) { + if (result != static_cast(file_info_.offset)) { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + return; + } + } else { + if (result != byte_range_.first_byte_position()) { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + return; + } } - set_expected_content_size(remaining_bytes_); NotifyHeadersComplete(); } diff --git a/atom/browser/net/asar/url_request_asar_job.h b/atom/browser/net/asar/url_request_asar_job.h index adcac85b37d..15a723d79e8 100644 --- a/atom/browser/net/asar/url_request_asar_job.h +++ b/atom/browser/net/asar/url_request_asar_job.h @@ -8,10 +8,12 @@ #include #include +#include "atom/browser/net/js_asker.h" #include "atom/common/asar/archive.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" namespace base { @@ -34,11 +36,20 @@ net::URLRequestJob* CreateJobFromPath( class URLRequestAsarJob : public net::URLRequestJob { public: URLRequestAsarJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - std::shared_ptr archive, - const base::FilePath& file_path, - const Archive::FileInfo& file_info, - const scoped_refptr& file_task_runner); + net::NetworkDelegate* network_delegate); + + void Initialize(const scoped_refptr file_task_runner, + const base::FilePath& file_path); + + protected: + virtual ~URLRequestAsarJob(); + + void InitializeAsarJob(const scoped_refptr file_task_runner, + std::shared_ptr archive, + const base::FilePath& file_path, + const Archive::FileInfo& file_info); + void InitializeFileJob(const scoped_refptr file_task_runner, + const base::FilePath& file_path); // net::URLRequestJob: void Start() override; @@ -46,12 +57,39 @@ class URLRequestAsarJob : public net::URLRequestJob { bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + bool IsRedirectResponse(GURL* location, int* http_status_code) override; + net::Filter* SetupFilter() const override; bool GetMimeType(std::string* mime_type) const override; - - protected: - virtual ~URLRequestAsarJob(); + void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; private: + // Meta information about the file. It's used as a member in the + // URLRequestFileJob and also passed between threads because disk access is + // necessary to obtain it. + struct FileMetaInfo { + FileMetaInfo(); + + // Size of the file. + int64 file_size; + // Mime type associated with the file. + std::string mime_type; + // Result returned from GetMimeTypeFromFile(), i.e. flag showing whether + // obtaining of the mime type was successful. + bool mime_type_result; + // Flag showing whether the file exists. + bool file_exists; + // Flag showing whether the file name actually refers to a directory. + bool is_directory; + }; + + // Fetches file info on a background thread. + static void FetchMetaInfo(const base::FilePath& file_path, + FileMetaInfo* meta_info); + + // Callback after fetching file info on a background thread. + void DidFetchMetaInfo(const FileMetaInfo* meta_info); + + // Callback after opening file on a background thread. void DidOpen(int result); @@ -62,14 +100,24 @@ class URLRequestAsarJob : public net::URLRequestJob { // Callback after data is asynchronously read from the file into |buf|. void DidRead(scoped_refptr buf, int result); + // The type of this job. + enum JobType { + TYPE_ERROR, + TYPE_ASAR, + TYPE_FILE, + }; + JobType type_; + std::shared_ptr archive_; base::FilePath file_path_; Archive::FileInfo file_info_; scoped_ptr stream_; - int64 remaining_bytes_; + FileMetaInfo meta_info_; + scoped_refptr file_task_runner_; - const scoped_refptr file_task_runner_; + net::HttpByteRange byte_range_; + int64 remaining_bytes_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc new file mode 100644 index 00000000000..eb6697b76f5 --- /dev/null +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -0,0 +1,40 @@ +// Copyright (c) 2014 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/net/url_request_async_asar_job.h" + +namespace atom { + +UrlRequestAsyncAsarJob::UrlRequestAsyncAsarJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + v8::Isolate* isolate, + const JavaScriptHandler& handler) + : JsAsker(request, network_delegate, isolate, + handler) { +} + +void UrlRequestAsyncAsarJob::StartAsync(scoped_ptr options) { + base::FilePath::StringType file_path; + if (options->IsType(base::Value::TYPE_DICTIONARY)) { + static_cast(options.get())->GetString( + "path", &file_path); + } else if (options->IsType(base::Value::TYPE_STRING)) { + options->GetAsString(&file_path); + } + + if (file_path.empty()) { + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_NOT_IMPLEMENTED)); + } else { + asar::URLRequestAsarJob::Initialize( + content::BrowserThread::GetBlockingPool()-> + GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN), + base::FilePath(file_path)); + asar::URLRequestAsarJob::Start(); + } +} + +} // namespace atom diff --git a/atom/browser/net/url_request_async_asar_job.h b/atom/browser/net/url_request_async_asar_job.h new file mode 100644 index 00000000000..0b9676e7f36 --- /dev/null +++ b/atom/browser/net/url_request_async_asar_job.h @@ -0,0 +1,30 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_ +#define ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_ + +#include "atom/browser/net/asar/url_request_asar_job.h" +#include "atom/browser/net/js_asker.h" + +namespace atom { + +// Like URLRequestAsarJob, but asks the JavaScript handler for file path. +class UrlRequestAsyncAsarJob : public JsAsker { + public: + UrlRequestAsyncAsarJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + v8::Isolate* isolate, + const JavaScriptHandler& handler); + + // JsAsker: + void StartAsync(scoped_ptr options) override; + + private: + DISALLOW_COPY_AND_ASSIGN(UrlRequestAsyncAsarJob); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_ diff --git a/filenames.gypi b/filenames.gypi index 2dc110ef859..260c9a4c8a1 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -156,6 +156,8 @@ 'atom/browser/net/http_protocol_handler.h', 'atom/browser/net/js_asker.cc', 'atom/browser/net/js_asker.h', + 'atom/browser/net/url_request_async_asar_job.cc', + 'atom/browser/net/url_request_async_asar_job.h', 'atom/browser/net/url_request_string_job.cc', 'atom/browser/net/url_request_string_job.h', 'atom/browser/net/url_request_buffer_job.cc', From ebb1ddc0df116a17aec7fb5e50ab355db6fc7169 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 15:39:33 +0800 Subject: [PATCH 28/55] Support converting Buffer to Value --- atom.gyp | 2 -- .../native_mate_converters/v8_value_converter.cc | 13 +++++++++++++ .../native_mate_converters/v8_value_converter.h | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/atom.gyp b/atom.gyp index cabb43d4f70..440eceee62d 100644 --- a/atom.gyp +++ b/atom.gyp @@ -224,8 +224,6 @@ # Defined in Chromium but not exposed in its gyp file. 'V8_USE_EXTERNAL_STARTUP_DATA', 'ENABLE_PLUGINS', - # Needed by Node. - 'NODE_WANT_INTERNALS=1', ], 'sources': [ '<@(lib_sources)', diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index 0d5a2576547..2270f0e0fd3 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" +#include "vendor/node/src/node_buffer.h" namespace atom { @@ -258,6 +259,10 @@ base::Value* V8ValueConverter::FromV8ValueImpl( return FromV8Object(val->ToObject(), state, isolate); } + if (node::Buffer::HasInstance(val)) { + return FromNodeBuffer(val, state, isolate); + } + if (val->IsObject()) { return FromV8Object(val->ToObject(), state, isolate); } @@ -305,6 +310,14 @@ base::Value* V8ValueConverter::FromV8Array( return result; } +base::Value* V8ValueConverter::FromNodeBuffer( + v8::Local value, + FromV8ValueState* state, + v8::Isolate* isolate) const { + return base::BinaryValue::CreateWithCopiedBuffer( + node::Buffer::Data(value), node::Buffer::Length(value)); +} + base::Value* V8ValueConverter::FromV8Object( v8::Local val, FromV8ValueState* state, diff --git a/atom/common/native_mate_converters/v8_value_converter.h b/atom/common/native_mate_converters/v8_value_converter.h index 3a0f6374ccb..db108ad9b04 100644 --- a/atom/common/native_mate_converters/v8_value_converter.h +++ b/atom/common/native_mate_converters/v8_value_converter.h @@ -48,7 +48,9 @@ class V8ValueConverter { base::Value* FromV8Array(v8::Local array, FromV8ValueState* state, v8::Isolate* isolate) const; - + base::Value* FromNodeBuffer(v8::Local value, + FromV8ValueState* state, + v8::Isolate* isolate) const; base::Value* FromV8Object(v8::Local object, FromV8ValueState* state, v8::Isolate* isolate) const; From 1f2d7d1cd8e54f2988f11ad38c6fe48426bbd575 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 20:37:52 +0800 Subject: [PATCH 29/55] Implement protocol.registerBufferProtocol --- atom/browser/api/atom_api_protocol.cc | 5 ++- atom/browser/lib/chrome-extension.coffee | 4 +-- atom/browser/net/url_request_buffer_job.cc | 37 +++++++++++++++++----- atom/browser/net/url_request_buffer_job.h | 15 +++++---- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 0bd6728b4cf..366b6732d93 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -7,8 +7,9 @@ #include "atom/browser/atom_browser_client.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/net/url_request_string_job.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_string_job.h" #include "atom/common/native_mate_converters/callback.h" #include "native_mate/dictionary.h" @@ -48,6 +49,8 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) .SetMethod("registerStringProtocol", &Protocol::RegisterProtocol) + .SetMethod("registerBufferProtocol", + &Protocol::RegisterProtocol) .SetMethod("registerFileProtocol", &Protocol::RegisterProtocol); } diff --git a/atom/browser/lib/chrome-extension.coffee b/atom/browser/lib/chrome-extension.coffee index ccb52d37a4b..df0d717cd9d 100644 --- a/atom/browser/lib/chrome-extension.coffee +++ b/atom/browser/lib/chrome-extension.coffee @@ -72,8 +72,8 @@ app.once 'ready', -> directory = getPathForHost parsed.hostname return callback() unless directory? callback path.join(directory, parsed.path) - protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, -> - console.error 'Unable to register chrome-extension protocol' + protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, (error) -> + console.error 'Unable to register chrome-extension protocol' if error BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) -> @devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});" diff --git a/atom/browser/net/url_request_buffer_job.cc b/atom/browser/net/url_request_buffer_job.cc index a8233b88da4..5cfb60a750e 100644 --- a/atom/browser/net/url_request_buffer_job.cc +++ b/atom/browser/net/url_request_buffer_job.cc @@ -13,13 +13,34 @@ namespace atom { URLRequestBufferJob::URLRequestBufferJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, - const std::string& mime_type, - const std::string& charset, - scoped_refptr data) - : net::URLRequestSimpleJob(request, network_delegate), - mime_type_(mime_type), - charset_(charset), - buffer_data_(data) { + v8::Isolate* isolate, + const JavaScriptHandler& handler) + : JsAsker(request, network_delegate, isolate, + handler) { +} + +void URLRequestBufferJob::StartAsync(scoped_ptr options) { + const base::BinaryValue* binary = nullptr; + if (options->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict = + static_cast(options.get()); + dict->GetString("mimeType", &mime_type_); + dict->GetString("charset", &charset_); + dict->GetBinary("data", &binary); + } else if (options->IsType(base::Value::TYPE_BINARY)) { + options->GetAsBinary(&binary); + } + + if (!binary) { + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_NOT_IMPLEMENTED)); + return; + } + + data_ = new base::RefCountedBytes( + reinterpret_cast(binary->GetBuffer()), + binary->GetSize()); + net::URLRequestSimpleJob::Start(); } int URLRequestBufferJob::GetRefCountedData( @@ -29,7 +50,7 @@ int URLRequestBufferJob::GetRefCountedData( const net::CompletionCallback& callback) const { *mime_type = mime_type_; *charset = charset_; - *data = buffer_data_; + *data = data_; return net::OK; } diff --git a/atom/browser/net/url_request_buffer_job.h b/atom/browser/net/url_request_buffer_job.h index cbdfbfa10d0..c72e5b83850 100644 --- a/atom/browser/net/url_request_buffer_job.h +++ b/atom/browser/net/url_request_buffer_job.h @@ -7,19 +7,22 @@ #include +#include "atom/browser/net/js_asker.h" +#include "atom/common/node_includes.h" #include "base/memory/ref_counted_memory.h" #include "net/url_request/url_request_simple_job.h" -#include "atom/common/node_includes.h" namespace atom { -class URLRequestBufferJob : public net::URLRequestSimpleJob { +class URLRequestBufferJob : public JsAsker { public: URLRequestBufferJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const std::string& mime_type, - const std::string& charset, - scoped_refptr data); + v8::Isolate* isolate, + const JavaScriptHandler& handler); + + // JsAsker: + void StartAsync(scoped_ptr options) override; // URLRequestSimpleJob: int GetRefCountedData(std::string* mime_type, @@ -30,7 +33,7 @@ class URLRequestBufferJob : public net::URLRequestSimpleJob { private: std::string mime_type_; std::string charset_; - scoped_refptr buffer_data_; + scoped_refptr data_; DISALLOW_COPY_AND_ASSIGN(URLRequestBufferJob); }; From f493eb34aedb5660990f03e5ebc6401ddad17bf0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 21:09:44 +0800 Subject: [PATCH 30/55] Implement protocol.registerHttpProtocol --- atom/browser/api/atom_api_protocol.cc | 5 ++- atom/browser/net/js_asker.cc | 4 +- atom/browser/net/js_asker.h | 4 +- atom/browser/net/url_request_buffer_job.h | 1 - atom/browser/net/url_request_fetch_job.cc | 55 +++++++++++++---------- atom/browser/net/url_request_fetch_job.h | 21 +++++---- 6 files changed, 52 insertions(+), 38 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 366b6732d93..c0c2e5b512c 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -9,6 +9,7 @@ #include "atom/browser/atom_browser_main_parts.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" #include "atom/browser/net/url_request_string_job.h" #include "atom/common/native_mate_converters/callback.h" #include "native_mate/dictionary.h" @@ -52,7 +53,9 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("registerBufferProtocol", &Protocol::RegisterProtocol) .SetMethod("registerFileProtocol", - &Protocol::RegisterProtocol); + &Protocol::RegisterProtocol) + .SetMethod("registerHttpProtocol", + &Protocol::RegisterProtocol); } void Protocol::RegisterStandardSchemes( diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index b53799b06fd..aa6192b057a 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -47,7 +47,9 @@ void HandlerCallback(v8::Isolate* isolate, V8ValueConverter converter; v8::Local context = args->isolate()->GetCurrentContext(); scoped_ptr options(converter.FromV8Value(value, context)); - holder->callback.Run(true, options.Pass()); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(holder->callback, true, base::Passed(&options))); } // func.bind(func, ...). diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 0f5f05856cd..4d7e888e15a 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -47,9 +47,7 @@ class JsAsker : public RequestJob { weak_factory_(this) {} // Subclass should do initailze work here. - virtual void StartAsync(scoped_ptr options) { - RequestJob::Start(); - } + virtual void StartAsync(scoped_ptr options) = 0; private: // RequestJob: diff --git a/atom/browser/net/url_request_buffer_job.h b/atom/browser/net/url_request_buffer_job.h index c72e5b83850..de1a41234fe 100644 --- a/atom/browser/net/url_request_buffer_job.h +++ b/atom/browser/net/url_request_buffer_job.h @@ -8,7 +8,6 @@ #include #include "atom/browser/net/js_asker.h" -#include "atom/common/node_includes.h" #include "base/memory/ref_counted_memory.h" #include "net/url_request/url_request_simple_job.h" diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 47ca0633c6c..7e51c26ba2b 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -75,42 +75,53 @@ class ResponsePiper : public net::URLFetcherResponseWriter { } // namespace URLRequestFetchJob::URLRequestFetchJob( - scoped_refptr request_context_getter, net::URLRequest* request, net::NetworkDelegate* network_delegate, - const GURL& url, - const std::string& method, - const std::string& referrer) - : net::URLRequestJob(request, network_delegate), + v8::Isolate* isolate, + const JavaScriptHandler& handler) + : JsAsker(request, network_delegate, isolate, handler), pending_buffer_size_(0) { +} + +void URLRequestFetchJob::StartAsync(scoped_ptr options) { + if (!options->IsType(base::Value::TYPE_DICTIONARY)) { + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_NOT_IMPLEMENTED)); + return; + } + + std::string url, method, referrer; + base::DictionaryValue* dict = + static_cast(options.get()); + dict->GetString("url", &url); + dict->GetString("method", &method); + dict->GetString("referrer", &referrer); + // Use |request|'s method if |method| is not specified. net::URLFetcher::RequestType request_type; if (method.empty()) - request_type = GetRequestType(request->method()); + request_type = GetRequestType(request()->method()); else request_type = GetRequestType(method); - fetcher_ = net::URLFetcher::Create(url, request_type, this); - // Use request context if provided else create one. - if (request_context_getter) - fetcher_->SetRequestContext(request_context_getter.get()); - else - fetcher_->SetRequestContext(GetRequestContext()); - + fetcher_ = net::URLFetcher::Create(GURL(url), request_type, this); + fetcher_->SetRequestContext(CreateRequestContext()); fetcher_->SaveResponseWithWriter(make_scoped_ptr(new ResponsePiper(this))); // Use |request|'s referrer if |referrer| is not specified. - if (referrer.empty()) { - fetcher_->SetReferrer(request->referrer()); - } else { + if (referrer.empty()) + fetcher_->SetReferrer(request()->referrer()); + else fetcher_->SetReferrer(referrer); - } // Use |request|'s headers. - fetcher_->SetExtraRequestHeaders(request->extra_request_headers().ToString()); + fetcher_->SetExtraRequestHeaders( + request()->extra_request_headers().ToString()); + + fetcher_->Start(); } -net::URLRequestContextGetter* URLRequestFetchJob::GetRequestContext() { +net::URLRequestContextGetter* URLRequestFetchJob::CreateRequestContext() { if (!url_request_context_getter_.get()) { auto task_runner = base::ThreadTaskRunnerHandle::Get(); net::URLRequestContextBuilder builder; @@ -150,12 +161,8 @@ int URLRequestFetchJob::DataAvailable(net::IOBuffer* buffer, int num_bytes) { return bytes_read; } -void URLRequestFetchJob::Start() { - fetcher_->Start(); -} - void URLRequestFetchJob::Kill() { - URLRequestJob::Kill(); + JsAsker::Kill(); fetcher_.reset(); } diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h index a14e8dd1aae..f2086c6366c 100644 --- a/atom/browser/net/url_request_fetch_job.h +++ b/atom/browser/net/url_request_fetch_job.h @@ -7,6 +7,7 @@ #include +#include "atom/browser/net/js_asker.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_job.h" @@ -15,22 +16,23 @@ namespace atom { class AtomBrowserContext; -class URLRequestFetchJob : public net::URLRequestJob, +class URLRequestFetchJob : public JsAsker, public net::URLFetcherDelegate { public: - URLRequestFetchJob(scoped_refptr context_getter, - net::URLRequest* request, + URLRequestFetchJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const GURL& url, - const std::string& method, - const std::string& referrer); + v8::Isolate* isolate, + const JavaScriptHandler& handler); - net::URLRequestContextGetter* GetRequestContext(); + // Called by response writer. void HeadersCompleted(); int DataAvailable(net::IOBuffer* buffer, int num_bytes); + protected: + // JsAsker: + void StartAsync(scoped_ptr options) override; + // net::URLRequestJob: - void Start() override; void Kill() override; bool ReadRawData(net::IOBuffer* buf, int buf_size, @@ -43,6 +45,9 @@ class URLRequestFetchJob : public net::URLRequestJob, void OnURLFetchComplete(const net::URLFetcher* source) override; private: + // Create a independent request context. + net::URLRequestContextGetter* CreateRequestContext(); + scoped_refptr url_request_context_getter_; scoped_ptr fetcher_; scoped_refptr pending_buffer_; From 225321b5802deb76bfbab0567b95706e1cf5e9d2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 21:32:52 +0800 Subject: [PATCH 31/55] Make the completion callback optional --- atom/browser/api/atom_api_protocol.cc | 12 +++++++---- atom/browser/api/atom_api_protocol.h | 21 +++++++++++++++++++ atom/browser/net/asar/url_request_asar_job.cc | 1 + atom/browser/net/js_asker.cc | 2 ++ atom/browser/net/url_request_string_job.h | 4 ++-- vendor/native_mate | 2 +- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index c0c2e5b512c..b7a4971a37d 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -49,13 +49,13 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( return mate::ObjectTemplateBuilder(isolate) .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) .SetMethod("registerStringProtocol", - &Protocol::RegisterProtocol) + &Protocol::JavaScriptRegisterProtocol) .SetMethod("registerBufferProtocol", - &Protocol::RegisterProtocol) + &Protocol::JavaScriptRegisterProtocol) .SetMethod("registerFileProtocol", - &Protocol::RegisterProtocol) + &Protocol::JavaScriptRegisterProtocol) .SetMethod("registerHttpProtocol", - &Protocol::RegisterProtocol); + &Protocol::JavaScriptRegisterProtocol); } void Protocol::RegisterStandardSchemes( @@ -65,6 +65,10 @@ void Protocol::RegisterStandardSchemes( void Protocol::OnIOCompleted( const CompletionCallback& callback, ProtocolError error) { + // The completion callback is optional. + if (callback.is_null()) + return; + v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 54dac9b13b9..233ee00a290 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -12,6 +12,8 @@ #include "atom/browser/net/atom_url_request_job_factory.h" #include "base/callback.h" #include "content/public/browser/browser_thread.h" +#include "native_mate/arguments.h" +#include "native_mate/dictionary.h" #include "native_mate/handle.h" #include "native_mate/wrappable.h" @@ -106,6 +108,25 @@ class Protocol : public mate::Wrappable { return PROTOCOL_FAIL; } + // Parse optional parameters for registerProtocol. + template + void JavaScriptRegisterProtocol(v8::Isolate* isolate, + const std::string& scheme, + mate::Arguments* args) { + // protocol.registerProtocol(scheme[, options], handler[, callback]); + mate::Dictionary options = mate::Dictionary::CreateEmpty(isolate); + Handler handler; + CompletionCallback callback; + args->GetNext(&options); + if (!args->GetNext(&handler)) { + args->ThrowError(); + return; + } + args->GetNext(&callback); + + RegisterProtocol(isolate, scheme, handler, callback); + } + // Convert error code to JS exception and call the callback. void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); diff --git a/atom/browser/net/asar/url_request_asar_job.cc b/atom/browser/net/asar/url_request_asar_job.cc index 33cb04c9ede..de019f6d942 100644 --- a/atom/browser/net/asar/url_request_asar_job.cc +++ b/atom/browser/net/asar/url_request_asar_job.cc @@ -5,6 +5,7 @@ #include "atom/browser/net/asar/url_request_asar_job.h" #include +#include #include "base/bind.h" #include "base/files/file_util.h" diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index aa6192b057a..bbaf093eb25 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -4,6 +4,8 @@ #include "atom/browser/net/js_asker.h" +#include + #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/v8_value_converter.h" #include "native_mate/function_template.h" diff --git a/atom/browser/net/url_request_string_job.h b/atom/browser/net/url_request_string_job.h index 7a2e23acab0..87b9181352c 100644 --- a/atom/browser/net/url_request_string_job.h +++ b/atom/browser/net/url_request_string_job.h @@ -5,11 +5,11 @@ #ifndef ATOM_BROWSER_NET_URL_REQUEST_STRING_JOB_H_ #define ATOM_BROWSER_NET_URL_REQUEST_STRING_JOB_H_ +#include + #include "atom/browser/net/js_asker.h" #include "net/url_request/url_request_simple_job.h" -#include - namespace atom { class URLRequestStringJob : public JsAsker { diff --git a/vendor/native_mate b/vendor/native_mate index 67d9eaa215e..24d31e20469 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 67d9eaa215e8727d86dc7b1f7a10be8699848f1f +Subproject commit 24d31e204698bafc65c50295167764fbb0f28bc0 From d9b845fcdfd5795aea716002b934a2835b892342 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 22:57:25 +0800 Subject: [PATCH 32/55] Make session parameter work with null value --- atom/browser/api/atom_api_protocol.h | 19 +++++++++---- atom/browser/net/js_asker.h | 28 +++++++++++++------ .../browser/net/url_request_async_asar_job.cc | 7 ++--- atom/browser/net/url_request_async_asar_job.h | 5 +--- atom/browser/net/url_request_buffer_job.cc | 8 ++---- atom/browser/net/url_request_buffer_job.h | 5 +--- atom/browser/net/url_request_fetch_job.cc | 16 +++++++---- atom/browser/net/url_request_fetch_job.h | 5 +--- atom/browser/net/url_request_string_job.cc | 9 ++---- atom/browser/net/url_request_string_job.h | 5 +--- 10 files changed, 55 insertions(+), 52 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 233ee00a290..22d89896cfd 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -62,18 +62,26 @@ class Protocol : public mate::Wrappable { class CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - CustomProtocolHandler(v8::Isolate* isolate, const Handler& handler) - : isolate_(isolate), handler_(handler) {} + CustomProtocolHandler( + v8::Isolate* isolate, + scoped_refptr request_context, + const Handler& handler) + : isolate_(isolate), + request_context_(request_context), + handler_(handler) {} ~CustomProtocolHandler() override {} net::URLRequestJob* MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const override { - return new RequestJob(request, network_delegate, isolate_, handler_); + RequestJob* request_job = new RequestJob(request, network_delegate); + request_job->SetHandlerInfo(isolate_, request_context_, handler_); + return request_job; } private: v8::Isolate* isolate_; + scoped_refptr request_context_; Protocol::Handler handler_; DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); @@ -101,7 +109,8 @@ class Protocol : public mate::Wrappable { if (job_factory_->IsHandledProtocol(scheme)) return PROTOCOL_REGISTERED; scoped_ptr> protocol_handler( - new CustomProtocolHandler(isolate(), handler)); + new CustomProtocolHandler( + isolate(), request_context_getter_, handler)); if (job_factory_->SetProtocolHandler(scheme, protocol_handler.Pass())) return PROTOCOL_OK; else @@ -135,7 +144,7 @@ class Protocol : public mate::Wrappable { scoped_refptr request_context_getter_; - AtomURLRequestJobFactory* job_factory_; // weak ref. + AtomURLRequestJobFactory* job_factory_; // weak ref DISALLOW_COPY_AND_ASSIGN(Protocol); }; diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 4d7e888e15a..63b3199890c 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -6,10 +6,12 @@ #define ATOM_BROWSER_NET_JS_ASKER_H_ #include "base/callback.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/values.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" +#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job.h" #include "v8/include/v8.h" @@ -37,18 +39,26 @@ bool IsErrorOptions(base::Value* value, int* error); template class JsAsker : public RequestJob { public: - JsAsker(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler) - : RequestJob(request, network_delegate), - isolate_(isolate), - handler_(handler), - weak_factory_(this) {} + JsAsker(net::URLRequest* request, net::NetworkDelegate* network_delegate) + : RequestJob(request, network_delegate), weak_factory_(this) {} + + // Called by |CustomProtocolHandler| to store handler related information. + void SetHandlerInfo( + v8::Isolate* isolate, + scoped_refptr request_context_getter, + const JavaScriptHandler& handler) { + isolate_ = isolate; + request_context_getter_ = request_context_getter; + handler_ = handler; + } // Subclass should do initailze work here. virtual void StartAsync(scoped_ptr options) = 0; + net::URLRequestContextGetter* request_context_getter() const { + return request_context_getter_.get(); + } + private: // RequestJob: void Start() override { @@ -75,7 +85,9 @@ class JsAsker : public RequestJob { } v8::Isolate* isolate_; + scoped_refptr request_context_getter_; JavaScriptHandler handler_; + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(JsAsker); diff --git a/atom/browser/net/url_request_async_asar_job.cc b/atom/browser/net/url_request_async_asar_job.cc index eb6697b76f5..ba0189e5f6e 100644 --- a/atom/browser/net/url_request_async_asar_job.cc +++ b/atom/browser/net/url_request_async_asar_job.cc @@ -8,11 +8,8 @@ namespace atom { UrlRequestAsyncAsarJob::UrlRequestAsyncAsarJob( net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler) - : JsAsker(request, network_delegate, isolate, - handler) { + net::NetworkDelegate* network_delegate) + : JsAsker(request, network_delegate) { } void UrlRequestAsyncAsarJob::StartAsync(scoped_ptr options) { diff --git a/atom/browser/net/url_request_async_asar_job.h b/atom/browser/net/url_request_async_asar_job.h index 0b9676e7f36..748b96d84d2 100644 --- a/atom/browser/net/url_request_async_asar_job.h +++ b/atom/browser/net/url_request_async_asar_job.h @@ -13,10 +13,7 @@ namespace atom { // Like URLRequestAsarJob, but asks the JavaScript handler for file path. class UrlRequestAsyncAsarJob : public JsAsker { public: - UrlRequestAsyncAsarJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler); + UrlRequestAsyncAsarJob(net::URLRequest*, net::NetworkDelegate*); // JsAsker: void StartAsync(scoped_ptr options) override; diff --git a/atom/browser/net/url_request_buffer_job.cc b/atom/browser/net/url_request_buffer_job.cc index 5cfb60a750e..7eb3aaed243 100644 --- a/atom/browser/net/url_request_buffer_job.cc +++ b/atom/browser/net/url_request_buffer_job.cc @@ -11,12 +11,8 @@ namespace atom { URLRequestBufferJob::URLRequestBufferJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler) - : JsAsker(request, network_delegate, isolate, - handler) { + net::URLRequest* request, net::NetworkDelegate* network_delegate) + : JsAsker(request, network_delegate) { } void URLRequestBufferJob::StartAsync(scoped_ptr options) { diff --git a/atom/browser/net/url_request_buffer_job.h b/atom/browser/net/url_request_buffer_job.h index de1a41234fe..e6fecdba830 100644 --- a/atom/browser/net/url_request_buffer_job.h +++ b/atom/browser/net/url_request_buffer_job.h @@ -15,10 +15,7 @@ namespace atom { class URLRequestBufferJob : public JsAsker { public: - URLRequestBufferJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler); + URLRequestBufferJob(net::URLRequest*, net::NetworkDelegate*); // JsAsker: void StartAsync(scoped_ptr options) override; diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 7e51c26ba2b..57fab397fd9 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -75,11 +75,8 @@ class ResponsePiper : public net::URLFetcherResponseWriter { } // namespace URLRequestFetchJob::URLRequestFetchJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler) - : JsAsker(request, network_delegate, isolate, handler), + net::URLRequest* request, net::NetworkDelegate* network_delegate) + : JsAsker(request, network_delegate), pending_buffer_size_(0) { } @@ -91,11 +88,13 @@ void URLRequestFetchJob::StartAsync(scoped_ptr options) { } std::string url, method, referrer; + base::Value* session = nullptr; base::DictionaryValue* dict = static_cast(options.get()); dict->GetString("url", &url); dict->GetString("method", &method); dict->GetString("referrer", &referrer); + dict->Get("session", &session); // Use |request|'s method if |method| is not specified. net::URLFetcher::RequestType request_type; @@ -105,9 +104,14 @@ void URLRequestFetchJob::StartAsync(scoped_ptr options) { request_type = GetRequestType(method); fetcher_ = net::URLFetcher::Create(GURL(url), request_type, this); - fetcher_->SetRequestContext(CreateRequestContext()); fetcher_->SaveResponseWithWriter(make_scoped_ptr(new ResponsePiper(this))); + // When |session| is set to |null| we use a new request context for fetch job. + if (session && session->IsType(base::Value::TYPE_NULL)) + fetcher_->SetRequestContext(CreateRequestContext()); + else + fetcher_->SetRequestContext(request_context_getter()); + // Use |request|'s referrer if |referrer| is not specified. if (referrer.empty()) fetcher_->SetReferrer(request()->referrer()); diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h index f2086c6366c..189cebf01b1 100644 --- a/atom/browser/net/url_request_fetch_job.h +++ b/atom/browser/net/url_request_fetch_job.h @@ -19,10 +19,7 @@ class AtomBrowserContext; class URLRequestFetchJob : public JsAsker, public net::URLFetcherDelegate { public: - URLRequestFetchJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler); + URLRequestFetchJob(net::URLRequest*, net::NetworkDelegate*); // Called by response writer. void HeadersCompleted(); diff --git a/atom/browser/net/url_request_string_job.cc b/atom/browser/net/url_request_string_job.cc index eec8176d734..428a87f54b1 100644 --- a/atom/browser/net/url_request_string_job.cc +++ b/atom/browser/net/url_request_string_job.cc @@ -10,12 +10,9 @@ namespace atom { -URLRequestStringJob::URLRequestStringJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler) - : JsAsker(request, network_delegate, isolate, - handler) { +URLRequestStringJob::URLRequestStringJob( + net::URLRequest* request, net::NetworkDelegate* network_delegate) + : JsAsker(request, network_delegate) { } void URLRequestStringJob::StartAsync(scoped_ptr options) { diff --git a/atom/browser/net/url_request_string_job.h b/atom/browser/net/url_request_string_job.h index 87b9181352c..713185c0cd1 100644 --- a/atom/browser/net/url_request_string_job.h +++ b/atom/browser/net/url_request_string_job.h @@ -14,10 +14,7 @@ namespace atom { class URLRequestStringJob : public JsAsker { public: - URLRequestStringJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - v8::Isolate* isolate, - const JavaScriptHandler& handler); + URLRequestStringJob(net::URLRequest*, net::NetworkDelegate*); // JsAsker: void StartAsync(scoped_ptr options) override; From 94c1fb32a7d69d30c3f84b66ed37f16cf6c9a033 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 23:07:15 +0800 Subject: [PATCH 33/55] Try work around VS's bug --- atom/browser/net/js_asker.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index bbaf093eb25..487033d156b 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -65,7 +65,8 @@ v8::Local BindFunctionWith(v8::Isolate* isolate, v8::Local bind_func = v8::Local::Cast(bind.ToLocalChecked()); std::vector> converted = { - func, mate::ConvertToV8(isolate, args)..., + v8::Local::Cast(func), + mate::ConvertToV8(isolate, args)..., }; return bind_func->Call( context, func, converted.size(), &converted.front()).ToLocalChecked(); From 78171e2072e5f1fc3797f561cfee5b8d7183fe70 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 23:14:20 +0800 Subject: [PATCH 34/55] Don't use C++11 to not crash VS --- atom/browser/net/js_asker.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index 487033d156b..b17027570f4 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -54,22 +54,20 @@ void HandlerCallback(v8::Isolate* isolate, base::Bind(holder->callback, true, base::Passed(&options))); } -// func.bind(func, ...). -template +// func.bind(func, arg1, arg2). +// NB(zcbenz): Using C++11 version crashes VS. v8::Local BindFunctionWith(v8::Isolate* isolate, v8::Local context, v8::Local func, - ArgTypes... args) { + v8::Local arg1, + v8::Local arg2) { v8::MaybeLocal bind = func->Get(mate::StringToV8(isolate, "bind")); CHECK(!bind.IsEmpty()); v8::Local bind_func = v8::Local::Cast(bind.ToLocalChecked()); - std::vector> converted = { - v8::Local::Cast(func), - mate::ConvertToV8(isolate, args)..., - }; + v8::Local converted[] = { func, arg1, arg2 }; return bind_func->Call( - context, func, converted.size(), &converted.front()).ToLocalChecked(); + context, func, arraysize(converted), converted).ToLocalChecked(); } // Generate the callback that will be passed to |handler|. @@ -86,8 +84,7 @@ v8::MaybeLocal GenerateCallback(v8::Isolate* isolate, v8::Local::New(isolate, g_handler_callback_); CallbackHolder* holder = new CallbackHolder; holder->callback = callback; - return BindFunctionWith(isolate, context, - handler_callback->GetFunction(), + return BindFunctionWith(isolate, context, handler_callback->GetFunction(), v8::External::New(isolate, holder), v8::Object::New(isolate)); } From d0ef43bd12095a4c71af4bf5dd1be5aacd29d0ef Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 12 Aug 2015 23:16:17 +0800 Subject: [PATCH 35/55] Completion callback is called on IO thread --- atom/browser/net/js_asker.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/browser/net/js_asker.cc b/atom/browser/net/js_asker.cc index b17027570f4..d838ae39638 100644 --- a/atom/browser/net/js_asker.cc +++ b/atom/browser/net/js_asker.cc @@ -41,7 +41,9 @@ void HandlerCallback(v8::Isolate* isolate, CHECK(holder); v8::Local value; if (!args->GetNext(&value)) { - holder->callback.Run(false, nullptr); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(holder->callback, false, nullptr)); return; } From 777f99193f1e09b0e4ef8614c051b0651cc904af Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 13:44:37 +0800 Subject: [PATCH 36/55] Update native_mate to fix VS compilation error --- vendor/native_mate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/native_mate b/vendor/native_mate index 24d31e20469..b41635e8092 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 24d31e204698bafc65c50295167764fbb0f28bc0 +Subproject commit b41635e80921bddbf1a36f030490e063cd593477 From 05fd81ebdc3d97eab89f4c99e38b5eecae5e112b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 19:26:18 +0800 Subject: [PATCH 37/55] Implement protocol.unregisterProtocol --- atom/browser/api/atom_api_protocol.cc | 29 +++++++++++++++++++++++---- atom/browser/api/atom_api_protocol.h | 28 +++++++------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index b7a4971a37d..7571ee0e837 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -49,13 +49,14 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( return mate::ObjectTemplateBuilder(isolate) .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes) .SetMethod("registerStringProtocol", - &Protocol::JavaScriptRegisterProtocol) + &Protocol::RegisterProtocol) .SetMethod("registerBufferProtocol", - &Protocol::JavaScriptRegisterProtocol) + &Protocol::RegisterProtocol) .SetMethod("registerFileProtocol", - &Protocol::JavaScriptRegisterProtocol) + &Protocol::RegisterProtocol) .SetMethod("registerHttpProtocol", - &Protocol::JavaScriptRegisterProtocol); + &Protocol::RegisterProtocol) + .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol); } void Protocol::RegisterStandardSchemes( @@ -63,6 +64,26 @@ void Protocol::RegisterStandardSchemes( atom::AtomBrowserClient::SetCustomSchemes(schemes); } +void Protocol::UnregisterProtocol( + const std::string& scheme, mate::Arguments* args) { + CompletionCallback callback; + args->GetNext(&callback); + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&Protocol::UnregisterProtocolInIO, + base::Unretained(this), scheme), + base::Bind(&Protocol::OnIOCompleted, + base::Unretained(this), callback)); +} + +Protocol::ProtocolError Protocol::UnregisterProtocolInIO( + const std::string& scheme) { + if (!job_factory_->HasProtocolHandler(scheme)) + return PROTOCOL_NOT_REGISTERED; + job_factory_->SetProtocolHandler(scheme, nullptr); + return PROTOCOL_OK; +} + void Protocol::OnIOCompleted( const CompletionCallback& callback, ProtocolError error) { // The completion callback is optional. diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 22d89896cfd..c409d34c434 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -92,10 +92,11 @@ class Protocol : public mate::Wrappable { // Register the protocol with certain request job. template - void RegisterProtocol(v8::Isolate* isolate, - const std::string& scheme, + void RegisterProtocol(const std::string& scheme, const Handler& handler, - const CompletionCallback& callback) { + mate::Arguments* args) { + CompletionCallback callback; + args->GetNext(&callback); content::BrowserThread::PostTaskAndReplyWithResult( content::BrowserThread::IO, FROM_HERE, base::Bind(&Protocol::RegisterProtocolInIO, @@ -117,24 +118,9 @@ class Protocol : public mate::Wrappable { return PROTOCOL_FAIL; } - // Parse optional parameters for registerProtocol. - template - void JavaScriptRegisterProtocol(v8::Isolate* isolate, - const std::string& scheme, - mate::Arguments* args) { - // protocol.registerProtocol(scheme[, options], handler[, callback]); - mate::Dictionary options = mate::Dictionary::CreateEmpty(isolate); - Handler handler; - CompletionCallback callback; - args->GetNext(&options); - if (!args->GetNext(&handler)) { - args->ThrowError(); - return; - } - args->GetNext(&callback); - - RegisterProtocol(isolate, scheme, handler, callback); - } + // Unregistered the protocol handler that handles |scheme|. + void UnregisterProtocol(const std::string& scheme, mate::Arguments* args); + ProtocolError UnregisterProtocolInIO(const std::string& scheme); // Convert error code to JS exception and call the callback. void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); From 374d83ed9c9acd1bdf154b7de6b1bd7c69ff7caf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 19:33:53 +0800 Subject: [PATCH 38/55] Implement protocol.isHandledProtocol --- atom/browser/api/atom_api_protocol.cc | 16 +++++++++++++++- atom/browser/api/atom_api_protocol.h | 8 +++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 7571ee0e837..9170f16b482 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -56,7 +56,8 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( &Protocol::RegisterProtocol) .SetMethod("registerHttpProtocol", &Protocol::RegisterProtocol) - .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol); + .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) + .SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol); } void Protocol::RegisterStandardSchemes( @@ -84,6 +85,19 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO( return PROTOCOL_OK; } +void Protocol::IsHandledProtocol(const std::string& scheme, + const BooleanCallback& callback) { + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&Protocol::IsHandledProtocolInIO, + base::Unretained(this), scheme), + callback); +} + +bool Protocol::IsHandledProtocolInIO(const std::string& scheme) { + return job_factory_->IsHandledProtocol(scheme); +} + void Protocol::OnIOCompleted( const CompletionCallback& callback, ProtocolError error) { // The completion callback is optional. diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index c409d34c434..05e3f607393 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -34,6 +34,7 @@ class Protocol : public mate::Wrappable { using Handler = base::Callback)>; using CompletionCallback = base::Callback)>; + using BooleanCallback = base::Callback; static mate::Handle Create( v8::Isolate* isolate, AtomBrowserContext* browser_context); @@ -118,10 +119,15 @@ class Protocol : public mate::Wrappable { return PROTOCOL_FAIL; } - // Unregistered the protocol handler that handles |scheme|. + // Unregister the protocol handler that handles |scheme|. void UnregisterProtocol(const std::string& scheme, mate::Arguments* args); ProtocolError UnregisterProtocolInIO(const std::string& scheme); + // Whether the protocol has handler registered. + void IsHandledProtocol(const std::string& scheme, + const BooleanCallback& callback); + bool IsHandledProtocolInIO(const std::string& scheme); + // Convert error code to JS exception and call the callback. void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); From 773e932e987bfafc2fa6d00ac8748c3b07b29023 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 20:10:05 +0800 Subject: [PATCH 39/55] Implement protocol.interceptProtocol --- atom/browser/api/atom_api_protocol.cc | 10 ++++++- atom/browser/api/atom_api_protocol.h | 40 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 9170f16b482..f190bae616c 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -57,7 +57,15 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("registerHttpProtocol", &Protocol::RegisterProtocol) .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) - .SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol); + .SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol) + .SetMethod("interceptStringProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptBufferProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptFileProtocol", + &Protocol::InterceptProtocol) + .SetMethod("interceptHttpProtocol", + &Protocol::InterceptProtocol); } void Protocol::RegisterStandardSchemes( diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 05e3f607393..ce8f087ad08 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -11,6 +11,7 @@ #include "atom/browser/net/atom_url_request_job_factory.h" #include "base/callback.h" +#include "base/containers/scoped_ptr_hash_map.h" #include "content/public/browser/browser_thread.h" #include "native_mate/arguments.h" #include "native_mate/dictionary.h" @@ -128,6 +129,39 @@ class Protocol : public mate::Wrappable { const BooleanCallback& callback); bool IsHandledProtocolInIO(const std::string& scheme); + // Replace the protocol handler with a new one. + template + void InterceptProtocol(const std::string& scheme, + const Handler& handler, + mate::Arguments* args) { + CompletionCallback callback; + args->GetNext(&callback); + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&Protocol::InterceptProtocolInIO, + base::Unretained(this), scheme, handler), + base::Bind(&Protocol::OnIOCompleted, + base::Unretained(this), callback)); + } + template + ProtocolError InterceptProtocolInIO(const std::string& scheme, + const Handler& handler) { + if (!job_factory_->IsHandledProtocol(scheme)) + return PROTOCOL_NOT_REGISTERED; + // It is possible a protocol is handled but can not be intercepted. + if (!job_factory_->HasProtocolHandler(scheme)) + return PROTOCOL_FAIL; + if (ContainsKey(original_protocols_, scheme)) + return PROTOCOL_INTERCEPTED; + scoped_ptr> protocol_handler( + new CustomProtocolHandler( + isolate(), request_context_getter_, handler)); + original_protocols_.set( + scheme, + job_factory_->ReplaceProtocol(scheme, protocol_handler.Pass())); + return PROTOCOL_OK; + } + // Convert error code to JS exception and call the callback. void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); @@ -136,6 +170,12 @@ class Protocol : public mate::Wrappable { scoped_refptr request_context_getter_; + // Map that stores the original protocols of schemes. + using OriginalProtocolsMap = base::ScopedPtrHashMap< + std::string, + scoped_ptr>; + OriginalProtocolsMap original_protocols_; + AtomURLRequestJobFactory* job_factory_; // weak ref DISALLOW_COPY_AND_ASSIGN(Protocol); From 741c8f3d983c4625c8b8b6b51b20dfce7768f7b2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 20:19:02 +0800 Subject: [PATCH 40/55] Implement protocol.uninterceptProtocol --- atom/browser/api/atom_api_protocol.cc | 24 +++++++++++++++++++++++- atom/browser/api/atom_api_protocol.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index f190bae616c..e2f536462f4 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -65,7 +65,8 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("interceptFileProtocol", &Protocol::InterceptProtocol) .SetMethod("interceptHttpProtocol", - &Protocol::InterceptProtocol); + &Protocol::InterceptProtocol) + .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); } void Protocol::RegisterStandardSchemes( @@ -106,6 +107,27 @@ bool Protocol::IsHandledProtocolInIO(const std::string& scheme) { return job_factory_->IsHandledProtocol(scheme); } +void Protocol::UninterceptProtocol( + const std::string& scheme, mate::Arguments* args) { + CompletionCallback callback; + args->GetNext(&callback); + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&Protocol::UninterceptProtocolInIO, + base::Unretained(this), scheme), + base::Bind(&Protocol::OnIOCompleted, + base::Unretained(this), callback)); +} + +Protocol::ProtocolError Protocol::UninterceptProtocolInIO( + const std::string& scheme) { + if (!original_protocols_.contains(scheme)) + return PROTOCOL_NOT_INTERCEPTED; + job_factory_->ReplaceProtocol(scheme, + original_protocols_.take_and_erase(scheme)); + return PROTOCOL_OK; +} + void Protocol::OnIOCompleted( const CompletionCallback& callback, ProtocolError error) { // The completion callback is optional. diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index ce8f087ad08..2e706c4157f 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -162,6 +162,10 @@ class Protocol : public mate::Wrappable { return PROTOCOL_OK; } + // Restore the |scheme| to its original protocol handler. + void UninterceptProtocol(const std::string& scheme, mate::Arguments* args); + ProtocolError UninterceptProtocolInIO(const std::string& scheme); + // Convert error code to JS exception and call the callback. void OnIOCompleted(const CompletionCallback& callback, ProtocolError error); From 02714d466cf761ce892ece919b3df5aeddbd34ad Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 21:21:23 +0800 Subject: [PATCH 41/55] Fix crash when requesting invalid url --- atom/browser/net/url_request_fetch_job.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 57fab397fd9..eacaada1935 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -96,6 +96,14 @@ void URLRequestFetchJob::StartAsync(scoped_ptr options) { dict->GetString("referrer", &referrer); dict->Get("session", &session); + // Check if URL is valid. + GURL formated_url(url); + if (!formated_url.is_valid()) { + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_INVALID_URL)); + return; + } + // Use |request|'s method if |method| is not specified. net::URLFetcher::RequestType request_type; if (method.empty()) @@ -103,7 +111,7 @@ void URLRequestFetchJob::StartAsync(scoped_ptr options) { else request_type = GetRequestType(method); - fetcher_ = net::URLFetcher::Create(GURL(url), request_type, this); + fetcher_ = net::URLFetcher::Create(formated_url, request_type, this); fetcher_->SaveResponseWithWriter(make_scoped_ptr(new ResponsePiper(this))); // When |session| is set to |null| we use a new request context for fetch job. From 467ba6b7a9f91eac4008fb468ae8479d8f022397 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 21:24:27 +0800 Subject: [PATCH 42/55] Rename protocol.isHandledProtocol to protocol.isProtocolHandled --- atom/browser/api/atom_api_protocol.cc | 10 +- atom/browser/api/atom_api_protocol.h | 4 +- spec/api-protocol-spec.coffee | 449 ++++++++++++-------------- spec/static/main.js | 2 +- 4 files changed, 222 insertions(+), 243 deletions(-) diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index e2f536462f4..f77f3229ed0 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -57,7 +57,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder( .SetMethod("registerHttpProtocol", &Protocol::RegisterProtocol) .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) - .SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol) + .SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled) .SetMethod("interceptStringProtocol", &Protocol::InterceptProtocol) .SetMethod("interceptBufferProtocol", @@ -94,16 +94,16 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO( return PROTOCOL_OK; } -void Protocol::IsHandledProtocol(const std::string& scheme, - const BooleanCallback& callback) { +void Protocol::IsProtocolHandled(const std::string& scheme, + const BooleanCallback& callback) { content::BrowserThread::PostTaskAndReplyWithResult( content::BrowserThread::IO, FROM_HERE, - base::Bind(&Protocol::IsHandledProtocolInIO, + base::Bind(&Protocol::IsProtocolHandledInIO, base::Unretained(this), scheme), callback); } -bool Protocol::IsHandledProtocolInIO(const std::string& scheme) { +bool Protocol::IsProtocolHandledInIO(const std::string& scheme) { return job_factory_->IsHandledProtocol(scheme); } diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index 2e706c4157f..966fcd8726b 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -125,9 +125,9 @@ class Protocol : public mate::Wrappable { ProtocolError UnregisterProtocolInIO(const std::string& scheme); // Whether the protocol has handler registered. - void IsHandledProtocol(const std::string& scheme, + void IsProtocolHandled(const std::string& scheme, const BooleanCallback& callback); - bool IsHandledProtocolInIO(const std::string& scheme); + bool IsProtocolHandledInIO(const std::string& scheme); // Replace the protocol handler with a new one. template diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index 4f2fb79da37..f42ce17287b 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -1,278 +1,257 @@ assert = require 'assert' -ipc = require 'ipc' http = require 'http' path = require 'path' remote = require 'remote' protocol = remote.require 'protocol' describe 'protocol module', -> - describe 'protocol.registerProtocol', -> - it 'error when scheme is already registered', (done) -> - register = -> - protocol.registerProtocol 'test1', ((request) ->), (error, scheme) -> - if error? - protocol.unregisterProtocol 'test1', (error, scheme) -> - assert.equal scheme, 'test1' - done() - else - assert.equal scheme, 'test1' - register() - register() + protocolName = 'sp' + text = 'valar morghulis' - it 'calls the callback when scheme is visited', (done) -> - protocol.registerProtocol 'test2', (request) -> - assert.equal request.url, 'test2://test2' - protocol.unregisterProtocol 'test2' - done() - $.get 'test2://test2', -> + afterEach (done) -> + protocol.unregisterProtocol protocolName, -> done() describe 'protocol.unregisterProtocol', -> - it 'throws error when scheme does not exist', -> - protocol.unregisterProtocol 'test3', (->), (error, scheme) -> - if (error) - assert.equal scheme, 'test3' + it 'returns error when scheme does not exist', (done) -> + protocol.unregisterProtocol 'not-exist', (error) -> + assert.notEqual error, null + done() + + describe 'protocol.register(Any)Protocol', -> + emptyHandler = (request, callback) -> callback() + it 'throws error when scheme is already registered', (done) -> + protocol.registerStringProtocol protocolName, emptyHandler, (error) -> + assert.equal error, null + protocol.registerBufferProtocol protocolName, emptyHandler, (error) -> + assert.notEqual error, null done() - describe 'registered protocol callback', -> - it 'returns string should send the string as request content', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.registerProtocol 'atom-string', handler + it 'does not crash when handler is called twice', (done) -> + doubleHandler = (request, callback) -> + callback(text) + callback() + protocol.registerStringProtocol protocolName, doubleHandler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) - $.ajax - url: 'atom-string://fake-host' - success: (data) -> - assert.equal data, handler() - protocol.unregisterProtocol 'atom-string' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-string' + it 'sends error when callback is called with nothing', (done) -> + protocol.registerBufferProtocol protocolName, emptyHandler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() - it 'returns RequestStringJob should send string', (done) -> - data = 'valar morghulis' - job = new protocol.RequestStringJob(mimeType: 'text/html', data: data) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-string-job', handler + it 'does not crash when callback is called in next tick', (done) -> + handler = (request, callback) -> + setImmediate -> callback(text) + protocol.registerStringProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) - $.ajax - url: 'atom-string-job://fake-host' - success: (response) -> - assert.equal response, data - protocol.unregisterProtocol 'atom-string-job' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-string-job' + describe 'protocol.registerStringProtocol', -> + it 'sends string as response', (done) -> + handler = (request, callback) -> callback(text) + protocol.registerStringProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) - it 'returns RequestErrorJob should send error', (done) -> - data = 'valar morghulis' - job = new protocol.RequestErrorJob(-6) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-error-job', handler + it 'sends object as response', (done) -> + handler = (request, callback) -> callback(data: text, mimeType: 'text/html') + protocol.registerStringProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data, statux, request) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) - $.ajax - url: 'atom-error-job://fake-host' - success: (response) -> - assert false, 'should not reach here' - error: (xhr, errorType, error) -> - assert errorType, 'error' - protocol.unregisterProtocol 'atom-error-job' - done() + it 'fails when sending object other than string', (done) -> + handler = (request, callback) -> callback(new Date) + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() - it 'returns RequestHttpJob should send respone', (done) -> + describe 'protocol.registerBufferProtocol', -> + buffer = new Buffer(text) + + it 'sends Buffer as response', (done) -> + handler = (request, callback) -> callback(buffer) + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + + it 'sends object as response', (done) -> + handler = (request, callback) -> callback(data: buffer, mimeType: 'text/html') + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data, statux, request) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + + it 'fails when sending string', (done) -> + handler = (request, callback) -> callback(text) + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() + + describe 'protocol.registerFileProtocol', -> + filePath = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'file1' + fileContent = require('fs').readFileSync(filePath) + + normalPath = path.join __dirname, 'fixtures', 'pages', 'a.html' + normalContent = require('fs').readFileSync(normalPath) + + it 'sends file path as response', (done) -> + handler = (request, callback) -> callback(filePath) + protocol.registerFileProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, String(fileContent) + done() + error: (xhr, errorType, error) -> + done(error) + + it 'sends object as response', (done) -> + handler = (request, callback) -> callback(path: filePath) + protocol.registerFileProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data, statux, request) -> + assert.equal data, String(fileContent) + done() + error: (xhr, errorType, error) -> + done(error) + + it 'can send normal file', (done) -> + handler = (request, callback) -> callback(normalPath) + protocol.registerFileProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, String(normalContent) + done() + error: (xhr, errorType, error) -> + done(error) + + it 'fails when sending unexist-file', (done) -> + fakeFilePath = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'not-exist' + handler = (request, callback) -> callback(fakeFilePath) + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() + + it 'fails when sending unsupported content', (done) -> + handler = (request, callback) -> callback(new Date) + protocol.registerBufferProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() + + describe 'protocol.registerHttpProtocol', -> + it 'sends url as response', (done) -> server = http.createServer (req, res) -> assert.notEqual req.headers.accept, '' - res.writeHead(200, {'Content-Type': 'text/plain'}) - res.end('hello') + res.end(text) server.close() server.listen 0, '127.0.0.1', -> {port} = server.address() url = "http://127.0.0.1:#{port}" - job = new protocol.RequestHttpJob({url}) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-http-job', handler + handler = (request, callback) -> callback({url}) + protocol.registerHttpProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + it 'fails when sending invalid url', (done) -> + handler = (request, callback) -> callback({url: 'url'}) + protocol.registerHttpProtocol protocolName, handler, (error) -> $.ajax - url: 'atom-http-job://fake-host' + url: "#{protocolName}://fake-host" success: (data) -> - assert.equal data, 'hello' - protocol.unregisterProtocol 'atom-http-job' - done() + done('request succeeded but it should not') error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-http-job' + assert.equal errorType, 'error' + done() - it 'returns RequestBufferJob should send buffer', (done) -> - data = new Buffer("hello") - job = new protocol.RequestBufferJob(data: data) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-buffer-job', handler - - $.ajax - url: 'atom-buffer-job://fake-host' - success: (response) -> - assert.equal response.length, data.length - buf = new Buffer(response.length) - buf.write(response) - assert buf.equals(data) - protocol.unregisterProtocol 'atom-buffer-job' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-buffer-job' - - it 'returns RequestFileJob should send file', (done) -> - job = new protocol.RequestFileJob(__filename) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-file-job', handler - - $.ajax - url: 'atom-file-job://' + __filename - success: (data) -> - content = require('fs').readFileSync __filename - assert.equal data, String(content) - protocol.unregisterProtocol 'atom-file-job' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-file-job' - - it 'returns RequestFileJob should send file from asar archive', (done) -> - p = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'file1' - job = new protocol.RequestFileJob(p) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-file-job', handler - - $.ajax - url: 'atom-file-job://' + p - success: (data) -> - content = require('fs').readFileSync(p) - assert.equal data, String(content) - protocol.unregisterProtocol 'atom-file-job' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-file-job' - - it 'returns RequestFileJob should send file from asar archive with unpacked file', (done) -> - p = path.join __dirname, 'fixtures', 'asar', 'unpack.asar', 'a.txt' - job = new protocol.RequestFileJob(p) - handler = remote.createFunctionWithReturnValue job - protocol.registerProtocol 'atom-file-job', handler - - $.ajax - url: 'atom-file-job://' + p - success: (response) -> - data = require('fs').readFileSync(p) - assert.equal response.length, data.length - buf = new Buffer(response.length) - buf.write(response) - assert buf.equals(data) - protocol.unregisterProtocol 'atom-file-job' - done() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - protocol.unregisterProtocol 'atom-file-job' + it 'fails when sending unsupported content', (done) -> + handler = (request, callback) -> callback(new Date) + protocol.registerHttpProtocol protocolName, handler, (error) -> + $.ajax + url: "#{protocolName}://fake-host" + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() describe 'protocol.isHandledProtocol', -> - it 'returns true if the file scheme can be handled', (done) -> + it 'returns true for file:', (done) -> protocol.isHandledProtocol 'file', (result) -> assert.equal result, true done() - it 'returns true if the http scheme can be handled', (done) -> + + it 'returns true for http:', (done) -> protocol.isHandledProtocol 'http', (result) -> assert.equal result, true done() - it 'returns true if the https scheme can be handled', (done) -> + + it 'returns true for https:', (done) -> protocol.isHandledProtocol 'https', (result) -> assert.equal result, true done() - it 'returns false if the atom scheme cannot be handled', (done) -> + + it 'returns false when scheme is not registred', (done) -> protocol.isHandledProtocol 'atom', (result) -> assert.equal result, false done() - - describe 'protocol.interceptProtocol', -> - it 'throws error when scheme is not a registered one', (done) -> - protocol.interceptProtocol 'test-intercept', ( ->), (error, scheme) -> - if error? - assert.equal scheme, 'test-intercept' - done() - - it 'throws error when scheme is a custom protocol', (done) -> - protocol.once 'unregistered', (scheme) -> - assert.equal scheme, 'atom' - done() - protocol.once 'registered', (scheme) -> - assert.equal scheme, 'atom' - protocol.interceptProtocol 'test-intercept', (->), (error, newScheme) -> - if error? - assert.equal newScheme, 'test-intercept' - protocol.unregisterProtocol scheme - protocol.registerProtocol('atom', ->) - - it 'returns original job when callback returns nothing', (done) -> - targetScheme = 'file' - protocol.once 'intercepted', (scheme) -> - assert.equal scheme, targetScheme - free = -> protocol.uninterceptProtocol targetScheme - $.ajax - url: "#{targetScheme}://#{__filename}", - success: -> - protocol.once 'unintercepted', (scheme) -> - assert.equal scheme, targetScheme - done() - free() - error: (xhr, errorType, error) -> - free() - assert false, 'Got error: ' + errorType + ' ' + error - protocol.interceptProtocol targetScheme, (request) -> - if process.platform is 'win32' - pathInUrl = path.normalize request.url.substr(8) - assert.equal pathInUrl.toLowerCase(), __filename.toLowerCase() - else - assert.equal request.url, "#{targetScheme}://#{__filename}" - - it 'can override original protocol handler', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.once 'intercepted', -> - free = -> protocol.uninterceptProtocol 'file' - $.ajax - url: 'file://fake-host' - success: (data) -> - protocol.once 'unintercepted', -> - assert.equal data, handler() - done() - free() - error: (xhr, errorType, error) -> - assert false, 'Got error: ' + errorType + ' ' + error - free() - protocol.interceptProtocol 'file', handler - - it 'can override http protocol handler', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.once 'intercepted', -> - protocol.uninterceptProtocol 'http' - done() - protocol.interceptProtocol 'http', handler - - it 'can override https protocol handler', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.once 'intercepted', -> - protocol.uninterceptProtocol 'https' - done() - protocol.interceptProtocol 'https', handler - - it 'can override ws protocol handler', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.once 'intercepted', -> - protocol.uninterceptProtocol 'ws' - done() - protocol.interceptProtocol 'ws', handler - - it 'can override wss protocol handler', (done) -> - handler = remote.createFunctionWithReturnValue 'valar morghulis' - protocol.once 'intercepted', -> - protocol.uninterceptProtocol 'wss' - done() - protocol.interceptProtocol 'wss', handler diff --git a/spec/static/main.js b/spec/static/main.js index 601926716e9..4eb415dab22 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -135,7 +135,7 @@ app.on('ready', function() { app.setApplicationMenu(menu); // Test if using protocol module would crash. - require('protocol').registerProtocol('test-if-crashes', function() {}); + require('protocol').registerStringProtocol('test-if-crashes', function() {}); window = new BrowserWindow({ title: 'Electron Tests', From a88f951b2f86aee7c6a47ca1977cc93aaf229f6e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 22:26:27 +0800 Subject: [PATCH 43/55] Always set headers for response When intercepting HTTP protocols Chromium will assume there is always headers set, so we have to provide headers for all the responses to avoid the crash. --- atom/browser/net/js_asker.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 63b3199890c..9c45446abcb 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -11,6 +11,7 @@ #include "base/values.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" +#include "net/http/http_response_headers.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job.h" #include "v8/include/v8.h" @@ -71,6 +72,9 @@ class JsAsker : public RequestJob { base::Bind(&JsAsker::OnResponse, weak_factory_.GetWeakPtr()))); } + void GetResponseInfo(net::HttpResponseInfo* info) override { + info->headers = new net::HttpResponseHeaders(""); + } // Called when the JS handler has sent the response, we need to decide whether // to start, or fail the job. From 62d5c89f62b9b66592e679003fbef822388aa008 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 13 Aug 2015 22:39:11 +0800 Subject: [PATCH 44/55] spec: Rewrite tests for new protocol API --- spec/api-protocol-spec.coffee | 109 ++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 12 deletions(-) diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index f42ce17287b..f540a63ec40 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -9,13 +9,8 @@ describe 'protocol module', -> text = 'valar morghulis' afterEach (done) -> - protocol.unregisterProtocol protocolName, -> done() - - describe 'protocol.unregisterProtocol', -> - it 'returns error when scheme does not exist', (done) -> - protocol.unregisterProtocol 'not-exist', (error) -> - assert.notEqual error, null - done() + protocol.unregisterProtocol protocolName, -> + protocol.uninterceptProtocol 'http', -> done() describe 'protocol.register(Any)Protocol', -> emptyHandler = (request, callback) -> callback() @@ -61,6 +56,12 @@ describe 'protocol module', -> error: (xhr, errorType, error) -> done(error) + describe 'protocol.unregisterProtocol', -> + it 'returns error when scheme does not exist', (done) -> + protocol.unregisterProtocol 'not-exist', (error) -> + assert.notEqual error, null + done() + describe 'protocol.registerStringProtocol', -> it 'sends string as response', (done) -> handler = (request, callback) -> callback(text) @@ -235,23 +236,107 @@ describe 'protocol module', -> assert.equal errorType, 'error' done() - describe 'protocol.isHandledProtocol', -> + describe 'protocol.isProtocolHandled', -> it 'returns true for file:', (done) -> - protocol.isHandledProtocol 'file', (result) -> + protocol.isProtocolHandled 'file', (result) -> assert.equal result, true done() it 'returns true for http:', (done) -> - protocol.isHandledProtocol 'http', (result) -> + protocol.isProtocolHandled 'http', (result) -> assert.equal result, true done() it 'returns true for https:', (done) -> - protocol.isHandledProtocol 'https', (result) -> + protocol.isProtocolHandled 'https', (result) -> assert.equal result, true done() it 'returns false when scheme is not registred', (done) -> - protocol.isHandledProtocol 'atom', (result) -> + protocol.isProtocolHandled 'no-exist', (result) -> assert.equal result, false done() + + it 'returns true for custom protocol', (done) -> + emptyHandler = (request, callback) -> callback() + protocol.registerStringProtocol protocolName, emptyHandler, (error) -> + assert.equal error, null + protocol.isProtocolHandled protocolName, (result) -> + assert.equal result, true + done() + + it 'returns true for intercepted protocol', (done) -> + emptyHandler = (request, callback) -> callback() + protocol.interceptStringProtocol 'http', emptyHandler, (error) -> + assert.equal error, null + protocol.isProtocolHandled 'http', (result) -> + assert.equal result, true + done() + + describe 'protocol.intercept(Any)Protocol', -> + emptyHandler = (request, callback) -> callback() + + it 'throws error when scheme is already intercepted', (done) -> + protocol.interceptStringProtocol 'http', emptyHandler, (error) -> + assert.equal error, null + protocol.interceptBufferProtocol 'http', emptyHandler, (error) -> + assert.notEqual error, null + done() + + it 'does not crash when handler is called twice', (done) -> + doubleHandler = (request, callback) -> + callback(text) + callback() + protocol.interceptStringProtocol 'http', doubleHandler, (error) -> + $.ajax + url: 'http://fake-host' + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + + it 'sends error when callback is called with nothing', (done) -> + protocol.interceptBufferProtocol 'http', emptyHandler, (error) -> + $.ajax + url: 'http://fake-host' + success: (data) -> + done('request succeeded but it should not') + error: (xhr, errorType, error) -> + assert.equal errorType, 'error' + done() + + describe 'protocol.interceptStringProtocol', -> + it 'can intercept http protocol', (done) -> + handler = (request, callback) -> callback(text) + protocol.interceptStringProtocol 'http', handler, (error) -> + $.ajax + url: 'http://fake-host' + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + + describe 'protocol.interceptBufferProtocol', -> + it 'can intercept http protocol', (done) -> + handler = (request, callback) -> callback(new Buffer(text)) + protocol.interceptBufferProtocol 'http', handler, (error) -> + $.ajax + url: 'http://fake-host' + success: (data) -> + assert.equal data, text + done() + error: (xhr, errorType, error) -> + done(error) + + describe 'protocol.uninterceptProtocol', -> + it 'returns error when scheme does not exist', (done) -> + protocol.uninterceptProtocol 'not-exist', (error) -> + assert.notEqual error, null + done() + + it 'returns error when scheme is not intercepted', (done) -> + protocol.uninterceptProtocol 'http', (error) -> + assert.notEqual error, null + done() From 86eb0a5eaabdac9c1724078ba8e77b5cfd5f96bf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 14 Aug 2015 12:40:03 +0800 Subject: [PATCH 45/55] Create both Uint8Array and ArrayBuffer from blink --- atom/renderer/atom_renderer_client.cc | 42 +++++++++++++++++++++------ vendor/node | 2 +- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index af526df9f75..04a89fed388 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -7,6 +7,7 @@ #include #include "atom/common/api/atom_bindings.h" +#include "atom/common/native_mate_converters/callback.h" #include "atom/common/node_bindings.h" #include "atom/common/options_switches.h" #include "atom/renderer/atom_render_view_observer.h" @@ -19,6 +20,8 @@ #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_thread.h" +#include "third_party/WebKit/public/web/WebArrayBuffer.h" +#include "third_party/WebKit/public/web/WebArrayBufferConverter.h" #include "third_party/WebKit/public/web/WebCustomElement.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebPluginParams.h" @@ -53,15 +56,35 @@ bool IsGuestFrame(blink::WebFrame* frame) { return frame->uniqueName().utf8() == "ATOM_SHELL_GUEST_WEB_VIEW"; } -void* BlinkAllocate(size_t size) { - void* ptr = nullptr; - WTF::ArrayBufferContents::allocateMemory( - size, WTF::ArrayBufferContents::DontInitialize, ptr); - return ptr; +// global.Uint8Array; +v8::Local GetUint8ArrayConstructor( + v8::Isolate* isolate, v8::Local context) { + v8::Local constructor = context->Global()->Get( + mate::StringToV8(isolate, "Uint8Array")); + return v8::Local::Cast(constructor); } -void BlinkFree(void* ptr, size_t size) { - WTF::ArrayBufferContents::freeMemory(ptr, size); +// new ArrayBuffer(size); +v8::Local BlinkArrayBufferCreate( + v8::Isolate* isolate, size_t size) { + blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(size, 1); + return v8::Local::Cast( + blink::WebArrayBufferConverter::toV8Value( + &buffer, isolate->GetCurrentContext()->Global(), isolate)); +} + +// new Uint8Array(array_buffer, offset, size); +v8::Local BlinkUint8ArrayCreate( + v8::Local ab, size_t offset, size_t size) { + v8::Local context = ab->CreationContext(); + v8::Isolate* isolate = context->GetIsolate(); + v8::Local constructor = + GetUint8ArrayConstructor(isolate, context); + v8::Local args[] = { + ab, mate::ConvertToV8(isolate, offset), mate::ConvertToV8(isolate, size) + }; + return v8::Local::Cast(constructor->NewInstance( + context, arraysize(args), args).ToLocalChecked()); } // Helper class to forward the messages to the client. @@ -103,8 +126,9 @@ void AtomRendererClient::WebKitInitialized() { blink::WebCustomElement::addEmbedderCustomElementName("webview"); blink::WebCustomElement::addEmbedderCustomElementName("browserplugin"); - // Override Node's Buffer allocator with WTF's allocator. - node::Buffer::SetAllocator(&BlinkAllocate, &BlinkFree); + // Override Node's ArrayBuffer with DOM's ArrayBuffer. + node::Buffer::SetArrayBufferCreator(&BlinkArrayBufferCreate, + &BlinkUint8ArrayCreate); node_bindings_->Initialize(); node_bindings_->PrepareMessageLoop(); diff --git a/vendor/node b/vendor/node index 6472143e364..81645132a9d 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 6472143e364343f73ee6a9e1b67902cc5c30f7ef +Subproject commit 81645132a9d3dfadb6404714e208d3b419f878ea From 7d97bb6fe0a6feef886d927ea894bcb2f3521577 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 14 Aug 2015 13:44:18 +0800 Subject: [PATCH 46/55] docs: Rewrite docs for new protocol API --- docs/api/protocol.md | 205 +++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 93 deletions(-) diff --git a/docs/api/protocol.md b/docs/api/protocol.md index 03e979615fe..a256bf30a73 100644 --- a/docs/api/protocol.md +++ b/docs/api/protocol.md @@ -1,7 +1,7 @@ # protocol -The `protocol` module can register a new protocol or intercept an existing -protocol, so you can customize the response to the requests for various protocols. +The `protocol` module can register a custom protocol or intercept an existing +protocol. An example of implementing a protocol that has the same effect with the `file://` protocol: @@ -12,130 +12,149 @@ var path = require('path'); app.on('ready', function() { var protocol = require('protocol'); - protocol.registerProtocol('atom', function(request) { - var url = request.url.substr(7) - return new protocol.RequestFileJob(path.normalize(__dirname + '/' + url)); - }, function (error, scheme) { - if (!error) - console.log(scheme, ' registered successfully') + protocol.registerFileProtocol('atom', function(request, callback) { + var url = request.url.substr(7); + callback({path: path.normalize(__dirname + '/' + url)}); + }, function (error) { + if (error) + console.error('Failed to register protocol') }); }); ``` -**Note:** This module can only be used after the `ready` event -was emitted. +**Note:** This module can only be used after the `ready` event was emitted. -## protocol.registerProtocol(scheme, handler, callback) +## protocol.registerStandardSchemes(schemes) + +* `schemes` Array - Custom schemes to be registered as standard schemes. + +A standard scheme adheres to what RFC 3986 calls +[generic URI syntax](https://tools.ietf.org/html/rfc3986#section-3). This +includes `file:` and `filesystem:`. + +## protocol.registerFileProtocol(scheme, handler[, completion]) * `scheme` String * `handler` Function -* `callback` Function +* `completion` Function -Registers a custom protocol of `scheme`, the `handler` would be called with -`handler(request)` when the a request with registered `scheme` is made. +Registers a protocol of `scheme` that will send file as response, the `handler` +will be called with `handler(request, callback)` when a `request` is going to be +created with `scheme`, and `completion` will be called with `completion(null)` +when `scheme` is successfully registered, or `completion(error)` when failed. -You need to return a request job in the `handler` to specify which type of -response you would like to send. +To handle the `request`, the `callback` should be called with either file's path +or an object that has `path` property, e.g. `callback(filePath)` or +`callback({path: filePath})`. + +When `callback` is called with nothing, or a number, or an object that has +`error` property, the `request` will be failed with the `error` number you +specified. For the available error numbers you can use, please check: +https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h By default the scheme is treated like `http:`, which is parsed differently from protocols that follows "generic URI syntax" like `file:`, so you probably want to call `protocol.registerStandardSchemes` to make your scheme treated as standard scheme. -## protocol.unregisterProtocol(scheme, callback) +## protocol.registerBufferProtocol(scheme, handler[, completion]) * `scheme` String -* `callback` Function +* `handler` Function +* `completion` Function + +Registers a protocol of `scheme` that will send `Buffer` as response, the +`callback` should be called with either an `Buffer` object, or an object that +has `data`, `mimeType`, `chart` properties. + +Example: + +```javascript +protocol.registerBufferProtocol('atom', function(request, callback) { + callback({mimeType: 'text/html', data: new Buffer('
Response
')}); +}, function (error) { + if (error) + console.error('Failed to register protocol') +}); +``` + +## protocol.registerStringProtocol(scheme, handler[, completion]) + +* `scheme` String +* `handler` Function +* `completion` Function + +Registers a protocol of `scheme` that will send `String` as response, the +`callback` should be called with either a `String`, or an object that +has `data`, `mimeType`, `chart` properties. + +## protocol.registerHttpProtocol(scheme, handler[, completion]) + +* `scheme` String +* `handler` Function +* `completion` Function + +Registers a protocol of `scheme` that will send a HTTP request as response, the +`callback` should be called with an object that has `url`, `method`, `referer`, +`session` properties. + +By default the HTTP request will reuse current session, if you want the request +to have different session you should specify `session` to `null`. + +## protocol.unregisterProtocol(scheme[, completion]) + +* `scheme` String +* `completion` Function Unregisters the custom protocol of `scheme`. -## protocol.registerStandardSchemes(value) - -* `value` Array - -`value` is an array of custom schemes to be registered as standard schemes. - -A standard scheme adheres to what RFC 3986 calls -[generic URI syntax](https://tools.ietf.org/html/rfc3986#section-3). This -includes `file:` and `filesystem:`. - -## protocol.isHandledProtocol(scheme, callback) +## protocol.isProtocolHandled(scheme, callback) * `scheme` String * `callback` Function -`callback` returns a boolean whether the `scheme` can be handled already. +The `callback` will be called with a boolean that indicates whether there is +already a handler for `scheme`. -## protocol.interceptProtocol(scheme, handler, callback) +## protocol.interceptFileProtocol(scheme, handler[, completion]) * `scheme` String * `handler` Function * `callback` Function -Intercepts an existing protocol with `scheme`, returning `null` or `undefined` -in `handler` would use the original protocol handler to handle the request. +Intercepts `scheme` protocol and use `handler` as the protocol's new handler +which sends file as response. -## protocol.uninterceptProtocol(scheme, callback) +## protocol.interceptStringProtocol(scheme, handler[, completion]) + +* `scheme` String +* `handler` Function +* `callback` Function + +Intercepts `scheme` protocol and use `handler` as the protocol's new handler +which sends String as response. + +## protocol.interceptBufferProtocol(scheme, handler[, completion]) + +* `scheme` String +* `handler` Function +* `callback` Function + +Intercepts `scheme` protocol and use `handler` as the protocol's new handler +which sends `Buffer` as response. + +## protocol.interceptHttpProtocol(scheme, handler[, completion]) + +* `scheme` String +* `handler` Function +* `callback` Function + +Intercepts `scheme` protocol and use `handler` as the protocol's new handler +which sends a new HTTP request as response. + +## protocol.uninterceptProtocol(scheme[, completion]) * `scheme` String * `callback` Function -Unintercepts a protocol. - -## Class: protocol.RequestFileJob(path) - -* `path` String - -Create a request job which would query a file of `path` and set corresponding -mime types. - -## Class: protocol.RequestStringJob(options) - -* `options` Object - * `mimeType` String - Default is `text/plain` - * `charset` String - Default is `UTF-8` - * `data` String - -Create a request job which sends a string as response. - -## Class: protocol.RequestBufferJob(options) - -* `options` Object - * `mimeType` String - Default is `application/octet-stream` - * `encoding` String - Default is `UTF-8` - * `data` Buffer - -Create a request job which sends a buffer as response. - -## Class: protocol.RequestHttpJob(options) - -* `options` Object - * `session` [Session](browser-window.md#class-session) - By default it is - the app's default session, setting it to `null` will create a new session - for the requests - * `url` String - * `method` String - Default is `GET` - * `referrer` String - -Send a request to `url` and pipe the response back. - -## Class: protocol.RequestErrorJob(code) - -* `code` Integer - -Create a request job which sets appropriate network error message to console. -Default message is `net::ERR_NOT_IMPLEMENTED`. Code should be in the following -range. - -* Ranges: - * 0- 99 System related errors - * 100-199 Connection related errors - * 200-299 Certificate errors - * 300-399 HTTP errors - * 400-499 Cache errors - * 500-599 ? - * 600-699 FTP errors - * 700-799 Certificate manager errors - * 800-899 DNS resolver errors - -Check the [network error list](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h) for code and message relations. +Remove the interceptor installed for `scheme` and restore its original handler. From c18ec7f5bc7424cf4e8021bbeda0e7c7b41e885e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 13:49:15 +0800 Subject: [PATCH 47/55] runas@3.x --- package.json | 2 +- spec/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1942bcbc9a0..2986a380c4e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "coffee-script": "^1.9.2", "coffeelint": "^1.9.4", "request": "*", - "runas": "^2.0.0" + "runas": "3.x" }, "private": true, "scripts": { diff --git a/spec/package.json b/spec/package.json index 6343832dcc8..a3b0d590eff 100644 --- a/spec/package.json +++ b/spec/package.json @@ -9,7 +9,7 @@ "graceful-fs": "3.0.5", "mocha": "2.1.0", "q": "0.9.7", - "runas": "2.x", + "runas": "3.x", "temp": "0.8.1", "walkdir": "0.0.7", "ws": "0.7.2" From 0ee6e5334a9d913cbe3f615a1418d998f05de0f0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 13:58:49 +0800 Subject: [PATCH 48/55] Now working at 0.31.0 --- atom.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom.gyp b/atom.gyp index 440eceee62d..08885b3ef53 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.30.4', + 'version%': '0.31.0', }, 'includes': [ 'filenames.gypi', From 1bd8a9869a17f78ef16e67d63f4e81cf2461676c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 14:18:04 +0800 Subject: [PATCH 49/55] Run build script on arm and ia32 Linux --- script/cibuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/cibuild b/script/cibuild index c282bb0275a..67623beba40 100755 --- a/script/cibuild +++ b/script/cibuild @@ -69,9 +69,9 @@ def main(): run_script('build.py', ['-c', 'R']) run_script('create-dist.py') run_script('upload.py') - elif PLATFORM == 'win32' or target_arch == 'x64': + else: run_script('build.py', ['-c', 'D']) - if PLATFORM != 'win32': + if PLATFORM != 'win32' and target_arch == 'x64': run_script('test.py', ['--ci']) run_script('clean.py') From bc5ebb99117891ba0becfa382fdc13a141e03c5b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 14:28:37 +0800 Subject: [PATCH 50/55] Update to io.js v3.1.0 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index 81645132a9d..205b013ac86 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 81645132a9d3dfadb6404714e208d3b419f878ea +Subproject commit 205b013ac86e5500678a791cd54f305580fa4f4b From 627fe75a6aa210b97169df2b47e23e2fbcf23cdd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 16:14:47 +0800 Subject: [PATCH 51/55] Update brightray to fix building on Linux --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index cb8f80f473a..b69b097f0e2 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit cb8f80f473a54fe1de72d478fd7809cf0c01fdb2 +Subproject commit b69b097f0e2ecafa3e293100101de2807426212c From 00e5290dc8417424c15344fbce96eb71382179f9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 14:21:27 +0800 Subject: [PATCH 52/55] win: Update libchromium to fix .pdb missing errors --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 9a5979bdbae..d67b00f0b4a 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'e667b7cc5a04bc8e64960d47079d99446a263e85' +LIBCHROMIUMCONTENT_COMMIT = 'e738bafd994983408ea6c0871a054984e41519fc' PLATFORM = { 'cygwin': 'win32', From cf6a904f957bfe44eb47728045652259ce532a74 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 16:21:20 +0800 Subject: [PATCH 53/55] win: Fix release build --- script/lib/config.py | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index d67b00f0b4a..c363a83a5f4 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'e738bafd994983408ea6c0871a054984e41519fc' +LIBCHROMIUMCONTENT_COMMIT = '42200d8ec0b77c7491d3a09611c23eb771e0862d' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/brightray b/vendor/brightray index b69b097f0e2..939a7b81428 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit b69b097f0e2ecafa3e293100101de2807426212c +Subproject commit 939a7b814282a6433b8d7e3c9cfc74451360c07f From 61b7a3afe301578e896dc5b96895d937b4885d30 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 16:27:29 +0800 Subject: [PATCH 54/55] No need to ship ffmpeg in dist --- script/create-dist.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/create-dist.py b/script/create-dist.py index dbecc0a1eb7..c978641df32 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -31,7 +31,6 @@ TARGET_BINARIES = { '{0}.exe'.format(PROJECT_NAME), # 'electron.exe' 'content_shell.pak', 'd3dcompiler_47.dll', - 'ffmpegsumo.dll', 'icudtl.dat', 'libEGL.dll', 'libGLESv2.dll', @@ -50,7 +49,6 @@ TARGET_BINARIES = { PROJECT_NAME, # 'electron' 'content_shell.pak', 'icudtl.dat', - 'libffmpegsumo.so', 'libnode.so', 'natives_blob.bin', 'snapshot_blob.bin', From d931a49e891363ee714df49cd084decbeb47ab8b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Aug 2015 18:02:58 +0800 Subject: [PATCH 55/55] Warn about removed protocol APIs --- atom/browser/api/lib/protocol.coffee | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/atom/browser/api/lib/protocol.coffee b/atom/browser/api/lib/protocol.coffee index 4a45c702507..13f2a6d1027 100644 --- a/atom/browser/api/lib/protocol.coffee +++ b/atom/browser/api/lib/protocol.coffee @@ -3,4 +3,22 @@ throw new Error('Can not initialize protocol module before app is ready') unless protocol = process.atomBinding('protocol').protocol +# Warn about removed APIs. +logAndThrow = (callback, message) -> + console.error message + if callback then callback(new Error(message)) else throw new Error(message) +protocol.registerProtocol = (scheme, handler, callback) -> + logAndThrow callback, + 'registerProtocol API has been replaced by the + register[File/Http/Buffer/String]Protocol API family, please + switch to the new APIs.' +protocol.isHandledProtocol = (scheme, callback) -> + logAndThrow callback, + 'isHandledProtocol API has been replaced by isProtocolHandled.' +protocol.interceptProtocol = (scheme, handler, callback) -> + logAndThrow callback, + 'interceptProtocol API has been replaced by the + intercept[File/Http/Buffer/String]Protocol API family, please + switch to the new APIs.' + module.exports = protocol