diff --git a/atom.gyp b/atom.gyp index ad3c5a8ef696..dbaf6db56298 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.36.6', + 'version%': '0.36.7', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 394014e8b27e..e54d7fee1769 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -367,6 +367,10 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( base::Bind(&Browser::ClearRecentDocuments, browser)) .SetMethod("setAppUserModelId", base::Bind(&Browser::SetAppUserModelID, browser)) +#if defined(OS_MACOSX) + .SetMethod("hide", base::Bind(&Browser::Hide, browser)) + .SetMethod("show", base::Bind(&Browser::Show, browser)) +#endif #if defined(OS_WIN) .SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser)) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index f186821e7d31..5a8befc9d1db 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -12,6 +12,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/node_includes.h" #include "base/memory/linked_ptr.h" +#include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "native_mate/dictionary.h" #include "net/base/filename_util.h" @@ -47,80 +48,49 @@ namespace atom { namespace api { namespace { + // The wrapDownloadItem funtion which is implemented in JavaScript using WrapDownloadItemCallback = base::Callback)>; WrapDownloadItemCallback g_wrap_download_item; -char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey"; - std::map>> g_download_item_objects; + } // namespace -DownloadItem::SavePathData::SavePathData(const base::FilePath& path) : - path_(path) { -} - -const base::FilePath& DownloadItem::SavePathData::path() { - return path_; -} - -DownloadItem::DownloadItem(content::DownloadItem* download_item) : - download_item_(download_item) { +DownloadItem::DownloadItem(content::DownloadItem* download_item) + : download_item_(download_item) { download_item_->AddObserver(this); + AttachAsUserData(download_item); } DownloadItem::~DownloadItem() { - if (download_item_) - OnDownloadDestroyed(download_item_); + if (download_item_) { + // Destroyed by either garbage collection or destroy(). + download_item_->RemoveObserver(this); + download_item_->Remove(); + } + + // Remove from the global map. + auto iter = g_download_item_objects.find(weak_map_id()); + if (iter != g_download_item_objects.end()) + g_download_item_objects.erase(iter); } void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { - download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated"); + if (download_item_->IsDone()) { + Emit("done", item->GetState()); + + // Destroy the item once item is downloaded. + base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure()); + } else { + Emit("updated"); + } } void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) { - download_item_->RemoveObserver(this); - auto iter = g_download_item_objects.find(download_item_->GetId()); - if (iter != g_download_item_objects.end()) - g_download_item_objects.erase(iter); download_item_ = nullptr; -} - -int64 DownloadItem::GetReceivedBytes() { - return download_item_->GetReceivedBytes(); -} - -int64 DownloadItem::GetTotalBytes() { - return download_item_->GetTotalBytes(); -} - -const GURL& DownloadItem::GetURL() { - return download_item_->GetURL(); -} - -std::string DownloadItem::GetMimeType() { - return download_item_->GetMimeType(); -} - -bool DownloadItem::HasUserGesture() { - return download_item_->HasUserGesture(); -} - -std::string DownloadItem::GetFilename() { - return base::UTF16ToUTF8(net::GenerateFileName(GetURL(), - GetContentDisposition(), - std::string(), - download_item_->GetSuggestedFilename(), - GetMimeType(), - std::string()).LossyDisplayName()); -} - -std::string DownloadItem::GetContentDisposition() { - return download_item_->GetContentDisposition(); -} - -void DownloadItem::SetSavePath(const base::FilePath& path) { - download_item_->SetUserData(UserDataKey(), new SavePathData(path)); + // Destroy the native class immediately when downloadItem is destroyed. + delete this; } void DownloadItem::Pause() { @@ -133,6 +103,48 @@ void DownloadItem::Resume() { void DownloadItem::Cancel() { download_item_->Cancel(true); + download_item_->Remove(); +} + +int64 DownloadItem::GetReceivedBytes() const { + return download_item_->GetReceivedBytes(); +} + +int64 DownloadItem::GetTotalBytes() const { + return download_item_->GetTotalBytes(); +} + +std::string DownloadItem::GetMimeType() const { + return download_item_->GetMimeType(); +} + +bool DownloadItem::HasUserGesture() const { + return download_item_->HasUserGesture(); +} + +std::string DownloadItem::GetFilename() const { + return base::UTF16ToUTF8(net::GenerateFileName(GetURL(), + GetContentDisposition(), + std::string(), + download_item_->GetSuggestedFilename(), + GetMimeType(), + std::string()).LossyDisplayName()); +} + +std::string DownloadItem::GetContentDisposition() const { + return download_item_->GetContentDisposition(); +} + +const GURL& DownloadItem::GetURL() const { + return download_item_->GetURL(); +} + +void DownloadItem::SetSavePath(const base::FilePath& path) { + save_path_ = path; +} + +base::FilePath DownloadItem::GetSavePath() const { + return save_path_; } // static @@ -145,29 +157,31 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate, .SetMethod("cancel", &DownloadItem::Cancel) .SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes) .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) - .SetMethod("getURL", &DownloadItem::GetURL) .SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) .SetMethod("getFilename", &DownloadItem::GetFilename) .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition) - .SetMethod("setSavePath", &DownloadItem::SetSavePath); + .SetMethod("getURL", &DownloadItem::GetURL) + .SetMethod("setSavePath", &DownloadItem::SetSavePath) + .SetMethod("getSavePath", &DownloadItem::GetSavePath); } // static mate::Handle DownloadItem::Create( v8::Isolate* isolate, content::DownloadItem* item) { + auto existing = TrackableObject::FromWrappedClass(isolate, item); + if (existing) + return mate::CreateHandle(isolate, static_cast(existing)); + auto handle = mate::CreateHandle(isolate, new DownloadItem(item)); g_wrap_download_item.Run(handle.ToV8()); - g_download_item_objects[item->GetId()] = make_linked_ptr( + + // Reference this object in case it got garbage collected. + g_download_item_objects[handle->weak_map_id()] = make_linked_ptr( new v8::Global(isolate, handle.ToV8())); return handle; } -// static -void* DownloadItem::UserDataKey() { - return &kDownloadItemSavePathKey; -} - void ClearWrapDownloadItem() { g_wrap_download_item.Reset(); } diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 471913c2266a..5806c0181768 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -20,22 +20,26 @@ namespace api { class DownloadItem : public mate::TrackableObject, public content::DownloadItem::Observer { public: - class SavePathData : public base::SupportsUserData::Data { - public: - explicit SavePathData(const base::FilePath& path); - const base::FilePath& path(); - private: - base::FilePath path_; - }; - static mate::Handle Create(v8::Isolate* isolate, content::DownloadItem* item); - static void* UserDataKey(); // mate::TrackableObject: static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); + void Pause(); + void Resume(); + void Cancel(); + int64 GetReceivedBytes() const; + int64 GetTotalBytes() const; + std::string GetMimeType() const; + bool HasUserGesture() const; + std::string GetFilename() const; + std::string GetContentDisposition() const; + const GURL& GetURL() const; + void SetSavePath(const base::FilePath& path); + base::FilePath GetSavePath() const; + protected: explicit DownloadItem(content::DownloadItem* download_item); ~DownloadItem(); @@ -44,19 +48,8 @@ class DownloadItem : public mate::TrackableObject, void OnDownloadUpdated(content::DownloadItem* download) override; void OnDownloadDestroyed(content::DownloadItem* download) override; - void Pause(); - void Resume(); - void Cancel(); - int64 GetReceivedBytes(); - int64 GetTotalBytes(); - std::string GetMimeType(); - bool HasUserGesture(); - std::string GetFilename(); - std::string GetContentDisposition(); - const GURL& GetURL(); - void SetSavePath(const base::FilePath& path); - private: + base::FilePath save_path_; content::DownloadItem* download_item_; DISALLOW_COPY_AND_ASSIGN(DownloadItem); diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 1cc76ebfa23d..e5c5198f0341 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -14,8 +14,10 @@ #include "atom/browser/api/save_page_handler.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/atom_permission_manager.h" #include "atom/browser/net/atom_cert_verifier.h" #include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/net_converter.h" @@ -34,6 +36,7 @@ #include "native_mate/object_template_builder.h" #include "net/base/load_flags.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/host_cache.h" #include "net/proxy/proxy_service.h" #include "net/proxy/proxy_config_service_fixed.h" #include "net/url_request/url_request_context.h" @@ -269,6 +272,19 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, RunCallbackInUI(callback); } +void ClearHostResolverCacheInIO( + const scoped_refptr& context_getter, + const base::Closure& callback) { + auto request_context = context_getter->GetURLRequestContext(); + auto cache = request_context->host_resolver()->GetHostCache(); + if (cache) { + cache->clear(); + DCHECK_EQ(0u, cache->size()); + if (!callback.is_null()) + RunCallbackInUI(callback); + } +} + } // namespace Session::Session(AtomBrowserContext* browser_context) @@ -397,6 +413,28 @@ void Session::SetCertVerifyProc(v8::Local val, browser_context_->cert_verifier()->SetVerifyProc(proc); } +void Session::SetPermissionRequestHandler(v8::Local val, + mate::Arguments* args) { + AtomPermissionManager::RequestHandler handler; + if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) { + args->ThrowError("Must pass null or function"); + return; + } + auto permission_manager = static_cast( + browser_context()->GetPermissionManager()); + permission_manager->SetPermissionRequestHandler(handler); +} + +void Session::ClearHostResolverCache(mate::Arguments* args) { + base::Closure callback; + args->GetNext(&callback); + + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&ClearHostResolverCacheInIO, + make_scoped_refptr(browser_context_->GetRequestContext()), + callback)); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -448,6 +486,9 @@ void Session::BuildPrototype(v8::Isolate* isolate, .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc) + .SetMethod("setPermissionRequestHandler", + &Session::SetPermissionRequestHandler) + .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache) .SetProperty("cookies", &Session::Cookies) .SetProperty("webRequest", &Session::WebRequest); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 37a5a45a6c95..02d8ba5cdec0 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -76,6 +76,9 @@ class Session: public mate::TrackableObject, void EnableNetworkEmulation(const mate::Dictionary& options); void DisableNetworkEmulation(); void SetCertVerifyProc(v8::Local proc, mate::Arguments* args); + void SetPermissionRequestHandler(v8::Local val, + mate::Arguments* args); + void ClearHostResolverCache(mate::Arguments* args); v8::Local Cookies(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b7b0576d8bfa..80e5b606ef8d 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -14,6 +14,7 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/native_window.h" +#include "atom/browser/web_contents_permission_helper.h" #include "atom/browser/web_contents_preferences.h" #include "atom/browser/web_view_guest_delegate.h" #include "atom/common/api/api_messages.h" @@ -263,6 +264,9 @@ WebContents::WebContents(v8::Isolate* isolate, // Save the preferences in C++. new WebContentsPreferences(web_contents, options); + // Intialize permission helper. + WebContentsPermissionHelper::CreateForWebContents(web_contents); + web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent()); if (is_guest) { @@ -387,6 +391,18 @@ void WebContents::HandleKeyboardEvent( void WebContents::EnterFullscreenModeForTab(content::WebContents* source, const GURL& origin) { + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(source); + auto callback = base::Bind(&WebContents::OnEnterFullscreenModeForTab, + base::Unretained(this), source, origin); + permission_helper->RequestFullscreenPermission(callback); +} + +void WebContents::OnEnterFullscreenModeForTab(content::WebContents* source, + const GURL& origin, + bool allowed) { + if (!allowed) + return; CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin); Emit("enter-html-full-screen"); } @@ -445,6 +461,24 @@ void WebContents::FindReply(content::WebContents* web_contents, } } +void WebContents::RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback) { + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(web_contents); + permission_helper->RequestMediaAccessPermission(request, callback); +} + +void WebContents::RequestToLockMouse( + content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) { + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(web_contents); + permission_helper->RequestPointerLockPermission(user_gesture); +} + void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) { // Do nothing, we override this method just to avoid compilation error since // there are two virtual functions named BeforeUnloadFired. diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index e00798b6c137..63c4a0177716 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -134,6 +134,11 @@ class WebContents : public mate::TrackableObject, void SetAllowTransparency(bool allow); bool IsGuest() const; + // Callback triggered on permission response. + void OnEnterFullscreenModeForTab(content::WebContents* source, + const GURL& origin, + bool allowed); + // Returns the web preferences of current WebContents. v8::Local GetWebPreferences(v8::Isolate* isolate); @@ -196,6 +201,14 @@ class WebContents : public mate::TrackableObject, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) override; + void RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback) override; + void RequestToLockMouse( + content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) override; // content::WebContentsObserver: void BeforeUnloadFired(const base::TimeTicks& proceed_time) override; diff --git a/atom/browser/api/lib/browser-window.js b/atom/browser/api/lib/browser-window.js index b71c85a19103..a9649f853d75 100644 --- a/atom/browser/api/lib/browser-window.js +++ b/atom/browser/api/lib/browser-window.js @@ -55,14 +55,16 @@ BrowserWindow.prototype._init = function() { })(this)); // Change window title to page title. - this.webContents.on('page-title-updated', (function(_this) { - return function(event, title) { - _this.emit('page-title-updated', event, title); - if (!event.defaultPrevented) { - return _this.setTitle(title); - } - }; - })(this)); + this.webContents.on('page-title-updated', (event, title) => { + // The page-title-updated event is not emitted immediately (see #3645), so + // when the callback is called the BrowserWindow might have been closed. + if (this.isDestroyed()) + return; + // Route the event to BrowserWindow. + this.emit('page-title-updated', event, title); + if (!event.defaultPrevented) + this.setTitle(title); + }); // Sometimes the webContents doesn't get focus when window is shown, so we have // to force focusing on webContents in this case. The safest way is to focus it diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 5ad8e69ffc74..1fe435673db6 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -15,6 +15,7 @@ #include "atom/browser/atom_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_speech_recognition_manager_delegate.h" #include "atom/browser/native_window.h" +#include "atom/browser/web_contents_permission_helper.h" #include "atom/browser/web_contents_preferences.h" #include "atom/browser/window_list.h" #include "atom/common/options_switches.h" @@ -281,6 +282,24 @@ brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( return new AtomBrowserMainParts; } +void AtomBrowserClient::WebNotificationAllowed( + int render_process_id, + const base::Callback& callback) { + content::WebContents* web_contents = content::WebContents::FromRenderViewHost( + content::RenderViewHost::FromID(render_process_id, kDefaultRoutingID)); + if (!web_contents) { + callback.Run(false); + return; + } + auto permission_helper = + WebContentsPermissionHelper::FromWebContents(web_contents); + if (!permission_helper) { + callback.Run(false); + return; + } + permission_helper->RequestWebNotificationPermission(callback); +} + void AtomBrowserClient::RenderProcessHostDestroyed( content::RenderProcessHost* host) { int process_id = host->GetID(); diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index 3c54fab40bc1..4af66cc041ae 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -81,6 +81,9 @@ class AtomBrowserClient : public brightray::BrowserClient, // brightray::BrowserClient: brightray::BrowserMainParts* OverrideCreateBrowserMainParts( const content::MainFunctionParams&) override; + void WebNotificationAllowed( + int render_process_id, + const base::Callback& callback) override; // content::RenderProcessHostObserver: void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index ac59f8c31330..be004c8f6db8 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -13,6 +13,7 @@ #include "atom/browser/net/atom_url_request_job_factory.h" #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/http_protocol_handler.h" +#include "atom/browser/atom_permission_manager.h" #include "atom/browser/web_view_manager.h" #include "atom/common/atom_version.h" #include "atom/common/chrome_version.h" @@ -169,6 +170,12 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() { return guest_manager_.get(); } +content::PermissionManager* AtomBrowserContext::GetPermissionManager() { + if (!permission_manager_.get()) + permission_manager_.reset(new AtomPermissionManager); + return permission_manager_.get(); +} + scoped_ptr AtomBrowserContext::CreateCertVerifier() { DCHECK(!cert_verifier_); cert_verifier_ = new AtomCertVerifier; diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 9c94a60c305b..d959adbc753a 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -14,6 +14,7 @@ namespace atom { class AtomDownloadManagerDelegate; class AtomCertVerifier; class AtomNetworkDelegate; +class AtomPermissionManager; class AtomURLRequestJobFactory; class WebViewManager; @@ -37,6 +38,7 @@ class AtomBrowserContext : public brightray::BrowserContext { // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::BrowserPluginGuestManager* GetGuestManager() override; + content::PermissionManager* GetPermissionManager() override; // brightray::BrowserContext: void RegisterPrefs(PrefRegistrySimple* pref_registry) override; @@ -52,6 +54,7 @@ class AtomBrowserContext : public brightray::BrowserContext { private: scoped_ptr download_manager_delegate_; scoped_ptr guest_manager_; + scoped_ptr permission_manager_; // Managed by brightray::BrowserContext. AtomCertVerifier* cert_verifier_; diff --git a/atom/browser/atom_download_manager_delegate.cc b/atom/browser/atom_download_manager_delegate.cc index a5f5cc6d8e4d..f5bdbbd8598d 100644 --- a/atom/browser/atom_download_manager_delegate.cc +++ b/atom/browser/atom_download_manager_delegate.cc @@ -109,16 +109,24 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget( download->GetForcedFilePath()); return true; } - base::SupportsUserData::Data* save_path = download->GetUserData( - atom::api::DownloadItem::UserDataKey()); - if (save_path) { - const base::FilePath& default_download_path = - static_cast(save_path)->path(); - callback.Run(default_download_path, - content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - default_download_path); - return true; + + // Try to get the save path from JS wrapper. + { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + api::DownloadItem* download_item = api::DownloadItem::FromWrappedClass( + isolate, download); + if (download_item) { + base::FilePath save_path = download_item->GetSavePath(); + if (!save_path.empty()) { + callback.Run(save_path, + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + save_path); + return true; + } + } } AtomBrowserContext* browser_context = static_cast( diff --git a/atom/browser/atom_permission_manager.cc b/atom/browser/atom_permission_manager.cc new file mode 100644 index 000000000000..e7fdaaffea71 --- /dev/null +++ b/atom/browser/atom_permission_manager.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_permission_manager.h" + +#include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/permission_type.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" + +namespace atom { + +namespace { + +// Must be kept in sync with atom_browser_client.cc +int kDefaultRoutingID = 2; + +bool WebContentsDestroyed(int process_id) { + auto rvh = content::RenderViewHost::FromID(process_id, kDefaultRoutingID); + if (rvh) { + auto contents = content::WebContents::FromRenderViewHost(rvh); + return contents->IsBeingDestroyed(); + } + + return true; +} + +} // namespace + +AtomPermissionManager::AtomPermissionManager() + : request_id_(0) { +} + +AtomPermissionManager::~AtomPermissionManager() { +} + +void AtomPermissionManager::SetPermissionRequestHandler( + const RequestHandler& handler) { + if (handler.is_null() && !pending_requests_.empty()) { + for (const auto& request : pending_requests_) { + if (!WebContentsDestroyed(request.second.render_process_id)) + request.second.callback.Run(content::PERMISSION_STATUS_DENIED); + } + pending_requests_.clear(); + } + request_handler_ = handler; +} + +int AtomPermissionManager::RequestPermission( + content::PermissionType permission, + content::RenderFrameHost* render_frame_host, + const GURL& requesting_origin, + bool user_gesture, + const ResponseCallback& response_callback) { + int process_id = render_frame_host->GetProcess()->GetID(); + + if (permission == content::PermissionType::MIDI_SYSEX) { + content::ChildProcessSecurityPolicy::GetInstance()-> + GrantSendMidiSysExMessage(process_id); + } + + if (!request_handler_.is_null()) { + auto web_contents = + content::WebContents::FromRenderFrameHost(render_frame_host); + ++request_id_; + auto callback = base::Bind(&AtomPermissionManager::OnPermissionResponse, + base::Unretained(this), + request_id_, + requesting_origin, + response_callback); + pending_requests_[request_id_] = { process_id, callback }; + request_handler_.Run(web_contents, permission, callback); + return request_id_; + } + + response_callback.Run(content::PERMISSION_STATUS_GRANTED); + return kNoPendingOperation; +} + +void AtomPermissionManager::OnPermissionResponse( + int request_id, + const GURL& origin, + const ResponseCallback& callback, + content::PermissionStatus status) { + auto request = pending_requests_.find(request_id); + if (request != pending_requests_.end()) { + if (!WebContentsDestroyed(request->second.render_process_id)) + callback.Run(status); + pending_requests_.erase(request); + } +} + +void AtomPermissionManager::CancelPermissionRequest(int request_id) { + auto request = pending_requests_.find(request_id); + if (request != pending_requests_.end()) { + if (!WebContentsDestroyed(request->second.render_process_id)) + request->second.callback.Run(content::PERMISSION_STATUS_DENIED); + pending_requests_.erase(request); + } +} + +void AtomPermissionManager::ResetPermission( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) { +} + +content::PermissionStatus AtomPermissionManager::GetPermissionStatus( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) { + return content::PERMISSION_STATUS_GRANTED; +} + +void AtomPermissionManager::RegisterPermissionUsage( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) { +} + +int AtomPermissionManager::SubscribePermissionStatusChange( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + const ResponseCallback& callback) { + return -1; +} + +void AtomPermissionManager::UnsubscribePermissionStatusChange( + int subscription_id) { +} + +} // namespace atom diff --git a/atom/browser/atom_permission_manager.h b/atom/browser/atom_permission_manager.h new file mode 100644 index 000000000000..4bebbbc84f29 --- /dev/null +++ b/atom/browser/atom_permission_manager.h @@ -0,0 +1,84 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_ +#define ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_ + +#include + +#include "base/callback.h" +#include "content/public/browser/permission_manager.h" + +namespace content { +class WebContents; +} + +namespace atom { + +class AtomPermissionManager : public content::PermissionManager { + public: + AtomPermissionManager(); + ~AtomPermissionManager() override; + + using ResponseCallback = + base::Callback; + using RequestHandler = + base::Callback; + + // Handler to dispatch permission requests in JS. + void SetPermissionRequestHandler(const RequestHandler& handler); + + // content::PermissionManager: + int RequestPermission( + content::PermissionType permission, + content::RenderFrameHost* render_frame_host, + const GURL& requesting_origin, + bool user_gesture, + const ResponseCallback& callback) override; + + protected: + void OnPermissionResponse(int request_id, + const GURL& url, + const ResponseCallback& callback, + content::PermissionStatus status); + + // content::PermissionManager: + void CancelPermissionRequest(int request_id) override; + void ResetPermission(content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + content::PermissionStatus GetPermissionStatus( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + void RegisterPermissionUsage(content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + int SubscribePermissionStatusChange( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + const base::Callback& callback) override; + void UnsubscribePermissionStatusChange(int subscription_id) override; + + private: + struct RequestInfo { + int render_process_id; + ResponseCallback callback; + }; + + RequestHandler request_handler_; + + std::map pending_requests_; + + int request_id_; + + DISALLOW_COPY_AND_ASSIGN(AtomPermissionManager); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_ATOM_PERMISSION_MANAGER_H_ diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 0b55fb600cff..2c44eaa107bc 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -77,6 +77,12 @@ class Browser : public WindowListObserver { void SetAppUserModelID(const base::string16& name); #if defined(OS_MACOSX) + // Hide the application. + void Hide(); + + // Show the application. + void Show(); + // Bounce the dock icon. enum BounceType { BOUNCE_CRITICAL = 0, diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 1eb7fabdab06..bc0be22dcae8 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -18,6 +18,14 @@ void Browser::Focus() { [[AtomApplication sharedApplication] activateIgnoringOtherApps:YES]; } +void Browser::Hide() { + [[AtomApplication sharedApplication] hide:nil]; +} + +void Browser::Show() { + [[AtomApplication sharedApplication] unhide:nil]; +} + void Browser::AddRecentDocument(const base::FilePath& path) { NSString* path_string = base::mac::FilePathToNSString(path); if (!path_string) @@ -103,7 +111,7 @@ void Browser::DockSetMenu(ui::MenuModel* model) { } void Browser::DockSetIcon(const gfx::Image& image) { - [[NSApplication sharedApplication] + [[AtomApplication sharedApplication] setApplicationIconImage:image.AsNSImage()]; } diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index 72a664f8cd00..1fd6f782de58 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -181,13 +181,6 @@ content::WebContents* CommonWebContentsDelegate::OpenURLFromTab( return source; } -void CommonWebContentsDelegate::RequestToLockMouse( - content::WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target) { - GetWebContents()->GotResponseToLockMouseRequest(true); -} - bool CommonWebContentsDelegate::CanOverscrollContent() const { return false; } diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index ee18f36660ee..83ef2850bd96 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -9,10 +9,10 @@ #include #include -#include "brightray/browser/default_web_contents_delegate.h" #include "brightray/browser/inspectable_web_contents_impl.h" #include "brightray/browser/inspectable_web_contents_delegate.h" #include "brightray/browser/inspectable_web_contents_view_delegate.h" +#include "content/public/browser/web_contents_delegate.h" namespace atom { @@ -21,7 +21,7 @@ class NativeWindow; class WebDialogHelper; class CommonWebContentsDelegate - : public brightray::DefaultWebContentsDelegate, + : public content::WebContentsDelegate, public brightray::InspectableWebContentsDelegate, public brightray::InspectableWebContentsViewDelegate { public: @@ -59,9 +59,6 @@ class CommonWebContentsDelegate content::WebContents* OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) override; - void RequestToLockMouse(content::WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target) override; bool CanOverscrollContent() const override; content::JavaScriptDialogManager* GetJavaScriptDialogManager( content::WebContents* source) override; diff --git a/atom/browser/lib/guest-view-manager.js b/atom/browser/lib/guest-view-manager.js index 40f59691e7a1..b41b9b3a0f5c 100644 --- a/atom/browser/lib/guest-view-manager.js +++ b/atom/browser/lib/guest-view-manager.js @@ -6,7 +6,38 @@ var slice = [].slice; // Doesn't exist in early initialization. var webViewManager = null; -var supportedWebViewEvents = ['load-commit', 'did-finish-load', 'did-fail-load', 'did-frame-finish-load', 'did-start-loading', 'did-stop-loading', 'did-get-response-details', 'did-get-redirect-request', 'dom-ready', 'console-message', 'devtools-opened', 'devtools-closed', 'devtools-focused', 'new-window', 'will-navigate', 'did-navigate', 'did-navigate-in-page', 'close', 'crashed', 'gpu-crashed', 'plugin-crashed', 'destroyed', 'page-title-updated', 'page-favicon-updated', 'enter-html-full-screen', 'leave-html-full-screen', 'media-started-playing', 'media-paused', 'found-in-page', 'did-change-theme-color']; +var supportedWebViewEvents = [ + 'load-commit', + 'did-finish-load', + 'did-fail-load', + 'did-frame-finish-load', + 'did-start-loading', + 'did-stop-loading', + 'did-get-response-details', + 'did-get-redirect-request', + 'dom-ready', + 'console-message', + 'devtools-opened', + 'devtools-closed', + 'devtools-focused', + 'new-window', + 'will-navigate', + 'did-navigate', + 'did-navigate-in-page', + 'close', + 'crashed', + 'gpu-crashed', + 'plugin-crashed', + 'destroyed', + 'page-title-updated', + 'page-favicon-updated', + 'enter-html-full-screen', + 'leave-html-full-screen', + 'media-started-playing', + 'media-paused', + 'found-in-page', + 'did-change-theme-color' +]; var nextInstanceId = 0; var guestInstances = {}; diff --git a/atom/browser/lib/rpc-server.js b/atom/browser/lib/rpc-server.js index b3e6ddc78322..2f2b739e4a14 100644 --- a/atom/browser/lib/rpc-server.js +++ b/atom/browser/lib/rpc-server.js @@ -162,12 +162,12 @@ var unwrapArgs = function(sender, args) { }); let callIntoRenderer = function(...args) { - if (rendererReleased) + if (rendererReleased || sender.isDestroyed()) throw new Error(`Attempting to call a function in a renderer window that has been closed or released. Function provided here: ${meta.location}.`); sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args)); }; v8Util.setDestructor(callIntoRenderer, function() { - if (!rendererReleased) + if (!rendererReleased && !sender.isDestroyed()) sender.send('ATOM_RENDERER_RELEASE_CALLBACK', meta.id); }); sender.callbacks.set(meta.id, callIntoRenderer); diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index ca91a1f8ca4c..74725c94dc5f 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,13 +17,13 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.36.6 + 0.36.7 CFBundleShortVersionString - 0.36.6 + 0.36.7 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion - 10.8.0 + 10.9.0 NSMainNibFile MainMenu NSPrincipalClass diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 4f4be2777bec..298d0bce73cf 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,36,6,0 - PRODUCTVERSION 0,36,6,0 + FILEVERSION 0,36,7,0 + PRODUCTVERSION 0,36,7,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.36.6" + VALUE "FileVersion", "0.36.7" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.36.6" + VALUE "ProductVersion", "0.36.7" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/browser/web_contents_permission_helper.cc b/atom/browser/web_contents_permission_helper.cc new file mode 100644 index 000000000000..f5ce414dd2ca --- /dev/null +++ b/atom/browser/web_contents_permission_helper.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/web_contents_permission_helper.h" + +#include + +#include "atom/browser/atom_permission_manager.h" +#include "brightray/browser/media/media_stream_devices_controller.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_process_host.h" + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPermissionHelper); + +namespace atom { + +namespace { + +void MediaAccessAllowed( + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback, + bool allowed) { + brightray::MediaStreamDevicesController controller(request, callback); + if (allowed) + controller.Accept(); + else + controller.Deny(content::MEDIA_DEVICE_PERMISSION_DENIED); +} + +void OnPointerLockResponse(content::WebContents* web_contents, bool allowed) { + if (web_contents) + web_contents->GotResponseToLockMouseRequest(allowed); +} + +void OnPermissionResponse(const base::Callback& callback, + content::PermissionStatus status) { + if (status == content::PERMISSION_STATUS_GRANTED) + callback.Run(true); + else + callback.Run(false); +} + +} // namespace + +WebContentsPermissionHelper::WebContentsPermissionHelper( + content::WebContents* web_contents) + : web_contents_(web_contents) { +} + +WebContentsPermissionHelper::~WebContentsPermissionHelper() { +} + +void WebContentsPermissionHelper::RequestPermission( + content::PermissionType permission, + const base::Callback& callback, + bool user_gesture) { + auto rfh = web_contents_->GetMainFrame(); + auto permission_manager = static_cast( + web_contents_->GetBrowserContext()->GetPermissionManager()); + auto origin = web_contents_->GetLastCommittedURL(); + permission_manager->RequestPermission( + permission, rfh, origin, user_gesture, + base::Bind(&OnPermissionResponse, callback)); +} + +void WebContentsPermissionHelper::RequestFullscreenPermission( + const base::Callback& callback) { + RequestPermission((content::PermissionType)(PermissionType::FULLSCREEN), + callback); +} + +void WebContentsPermissionHelper::RequestMediaAccessPermission( + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& response_callback) { + auto callback = base::Bind(&MediaAccessAllowed, request, response_callback); + // The permission type doesn't matter here, AUDIO_CAPTURE/VIDEO_CAPTURE + // are presented as same type in content_converter.h. + RequestPermission(content::PermissionType::AUDIO_CAPTURE, callback); +} + +void WebContentsPermissionHelper::RequestWebNotificationPermission( + const base::Callback& callback) { + RequestPermission(content::PermissionType::NOTIFICATIONS, callback); +} + +void WebContentsPermissionHelper::RequestPointerLockPermission( + bool user_gesture) { + RequestPermission((content::PermissionType)(PermissionType::POINTER_LOCK), + base::Bind(&OnPointerLockResponse, web_contents_), + user_gesture); +} + +} // namespace atom diff --git a/atom/browser/web_contents_permission_helper.h b/atom/browser/web_contents_permission_helper.h new file mode 100644 index 000000000000..90ae6dff56f5 --- /dev/null +++ b/atom/browser/web_contents_permission_helper.h @@ -0,0 +1,50 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_ +#define ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_ + +#include "content/public/browser/permission_type.h" +#include "content/public/browser/web_contents_user_data.h" +#include "content/public/common/media_stream_request.h" + +namespace atom { + +// Applies the permission requested for WebContents. +class WebContentsPermissionHelper + : public content::WebContentsUserData { + public: + ~WebContentsPermissionHelper() override; + + enum class PermissionType { + POINTER_LOCK = static_cast(content::PermissionType::NUM) + 1, + FULLSCREEN + }; + + void RequestFullscreenPermission( + const base::Callback& callback); + void RequestMediaAccessPermission( + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback); + void RequestWebNotificationPermission( + const base::Callback& callback); + void RequestPointerLockPermission(bool user_gesture); + + private: + explicit WebContentsPermissionHelper(content::WebContents* web_contents); + friend class content::WebContentsUserData; + + void RequestPermission( + content::PermissionType permission, + const base::Callback& callback, + bool user_gesture = false); + + content::WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsPermissionHelper); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_WEB_CONTENTS_PERMISSION_HELPER_H_ diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index 7527932b9771..35451410a8d9 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -130,14 +130,20 @@ Archive::Archive(const base::FilePath& path) Archive::~Archive() { #if defined(OS_WIN) - if (fd_ != -1) + if (fd_ != -1) { _close(fd_); + // Don't close the handle since we already closed the fd. + file_.TakePlatformFile(); + } #endif } bool Archive::Init() { if (!file_.IsValid()) { - LOG(ERROR) << base::File::ErrorToString(file_.error_details()); + if (file_.error_details() != base::File::FILE_ERROR_NOT_FOUND) { + LOG(WARNING) << "Opening " << path_.value() + << ": " << base::File::ErrorToString(file_.error_details()); + } return false; } diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 13d71dc47a87..a4f886c7e7d5 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 0 #define ATOM_MINOR_VERSION 36 -#define ATOM_PATCH_VERSION 6 +#define ATOM_PATCH_VERSION 7 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/atom/common/native_mate_converters/content_converter.cc b/atom/common/native_mate_converters/content_converter.cc index d79094f79d43..699f101d0e4b 100644 --- a/atom/common/native_mate_converters/content_converter.cc +++ b/atom/common/native_mate_converters/content_converter.cc @@ -7,6 +7,8 @@ #include #include +#include "atom/browser/api/atom_api_web_contents.h" +#include "atom/browser/web_contents_permission_helper.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "content/public/browser/web_contents.h" @@ -98,6 +100,55 @@ v8::Local Converter::ToV8( return mate::ConvertToV8(isolate, dict); } +// static +bool Converter::FromV8( + v8::Isolate* isolate, + v8::Local val, + content::PermissionStatus* out) { + bool result; + if (!ConvertFromV8(isolate, val, &result)) + return false; + + if (result) + *out = content::PERMISSION_STATUS_GRANTED; + else + *out = content::PERMISSION_STATUS_DENIED; + + return true; +} + +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, const content::PermissionType& val) { + using PermissionType = atom::WebContentsPermissionHelper::PermissionType; + switch (val) { + case content::PermissionType::MIDI_SYSEX: + return StringToV8(isolate, "midiSysex"); + case content::PermissionType::PUSH_MESSAGING: + return StringToV8(isolate, "pushMessaging"); + case content::PermissionType::NOTIFICATIONS: + return StringToV8(isolate, "notifications"); + case content::PermissionType::GEOLOCATION: + return StringToV8(isolate, "geolocation"); + case content::PermissionType::AUDIO_CAPTURE: + case content::PermissionType::VIDEO_CAPTURE: + return StringToV8(isolate, "media"); + case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: + return StringToV8(isolate, "mediaKeySystem"); + case content::PermissionType::MIDI: + return StringToV8(isolate, "midi"); + default: + break; + } + + if (val == (content::PermissionType)(PermissionType::POINTER_LOCK)) + return StringToV8(isolate, "pointerLock"); + else if (val == (content::PermissionType)(PermissionType::FULLSCREEN)) + return StringToV8(isolate, "fullscreen"); + + return StringToV8(isolate, "unknown"); +} + // static bool Converter::FromV8( v8::Isolate* isolate, @@ -119,4 +170,10 @@ bool Converter::FromV8( return true; } +// static +v8::Local Converter::ToV8( + v8::Isolate* isolate, content::WebContents* val) { + return atom::api::WebContents::CreateFrom(isolate, val).ToV8(); +} + } // namespace mate diff --git a/atom/common/native_mate_converters/content_converter.h b/atom/common/native_mate_converters/content_converter.h index a5708e022b57..b1a42b6897ca 100644 --- a/atom/common/native_mate_converters/content_converter.h +++ b/atom/common/native_mate_converters/content_converter.h @@ -7,7 +7,9 @@ #include +#include "content/public/browser/permission_type.h" #include "content/public/common/menu_item.h" +#include "content/public/common/permission_status.mojom.h" #include "content/public/common/stop_find_action.h" #include "native_mate/converter.h" @@ -33,12 +35,30 @@ struct Converter { const ContextMenuParamsWithWebContents& val); }; +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + content::PermissionStatus* out); +}; + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + const content::PermissionType& val); +}; + template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, content::StopFindAction* out); }; +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + content::WebContents* val); +}; + } // namespace mate #endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_ diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 3c97db4b9788..a996bd0efb25 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -9,6 +9,7 @@ #include "atom/common/api/api_messages.h" #include "atom/common/api/atom_bindings.h" +#include "atom/common/api/event_emitter_caller.h" #include "atom/common/node_bindings.h" #include "atom/common/node_includes.h" #include "atom/common/options_switches.h" @@ -47,17 +48,27 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver { AtomRenderFrameObserver(content::RenderFrame* frame, AtomRendererClient* renderer_client) : content::RenderFrameObserver(frame), + world_id_(-1), renderer_client_(renderer_client) {} // content::RenderFrameObserver: void DidCreateScriptContext(v8::Handle context, int extension_group, - int world_id) { - renderer_client_->DidCreateScriptContext( - render_frame()->GetWebFrame(), context); + int world_id) override { + if (world_id_ != -1 && world_id_ != world_id) + return; + world_id_ = world_id; + renderer_client_->DidCreateScriptContext(context); + } + void WillReleaseScriptContext(v8::Local context, + int world_id) override { + if (world_id_ != world_id) + return; + renderer_client_->WillReleaseScriptContext(context); } private: + int world_id_; AtomRendererClient* renderer_client_; DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver); @@ -108,10 +119,15 @@ void AtomRendererClient::RenderThreadStarted() { void AtomRendererClient::RenderFrameCreated( content::RenderFrame* render_frame) { new PepperHelper(render_frame); - new AtomRenderFrameObserver(render_frame, this); // Allow file scheme to handle service worker by default. blink::WebSecurityPolicy::registerURLSchemeAsAllowingServiceWorkers("file"); + + // Only insert node integration for the main frame. + if (!render_frame->IsMainFrame()) + return; + + new AtomRenderFrameObserver(render_frame, this); } void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) { @@ -139,12 +155,7 @@ bool AtomRendererClient::OverrideCreatePlugin( } void AtomRendererClient::DidCreateScriptContext( - blink::WebFrame* frame, v8::Handle context) { - // Only insert node integration for the main frame. - if (frame->parent()) - return; - // Give the node loop a run to make sure everything is ready. node_bindings_->RunMessageLoop(); @@ -162,6 +173,12 @@ void AtomRendererClient::DidCreateScriptContext( node_bindings_->LoadEnvironment(env); } +void AtomRendererClient::WillReleaseScriptContext( + v8::Handle context) { + node::Environment* env = node::Environment::GetCurrent(context); + mate::EmitEvent(env->isolate(), env->process_object(), "exit"); +} + bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame, const GURL& url, const std::string& http_method, diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index beeeb9d530b0..59b407ba1efb 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -22,8 +22,8 @@ class AtomRendererClient : public content::ContentRendererClient, AtomRendererClient(); virtual ~AtomRendererClient(); - void DidCreateScriptContext(blink::WebFrame* frame, - v8::Handle context); + void DidCreateScriptContext(v8::Handle context); + void WillReleaseScriptContext(v8::Handle context); private: enum NodeIntegration { diff --git a/atom/renderer/lib/init.js b/atom/renderer/lib/init.js index d25dbfbbbb85..340a1ef50536 100644 --- a/atom/renderer/lib/init.js +++ b/atom/renderer/lib/init.js @@ -1,4 +1,4 @@ -'user strict'; +'use strict'; const events = require('events'); const path = require('path'); @@ -106,11 +106,6 @@ if (nodeIntegration === 'true' || nodeIntegration === 'all' || nodeIntegration = return false; } }; - - // Emit the 'exit' event when page is unloading. - window.addEventListener('unload', function() { - return process.emit('exit'); - }); } else { // Delete Node's symbols after the Environment has been loaded. process.once('loaded', function() { diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 4aa4632d35e5..5257f0c12f98 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -1,4 +1,4 @@ -'user strict'; +'use strict'; const deprecate = require('electron').deprecate; const webFrame = require('electron').webFrame; diff --git a/docs-translations/es/tutorial/application-distribution.md b/docs-translations/es/tutorial/application-distribution.md index c957332dd862..5966cdad7ec4 100644 --- a/docs-translations/es/tutorial/application-distribution.md +++ b/docs-translations/es/tutorial/application-distribution.md @@ -61,8 +61,7 @@ de distribuirlo a los usuarios. ### Windows Puedes renombrar `electron.exe` a cualquier nombre que desees, y editar su ícono -y otra información con herramientas como [rcedit](https://github.com/atom/rcedit) -o [ResEdit](http://www.resedit.net). +y otra información con herramientas como [rcedit](https://github.com/atom/rcedit). ### OSX diff --git a/docs-translations/jp/api/app.md b/docs-translations/jp/api/app.md index d0df22bb4045..8d1099373589 100644 --- a/docs-translations/jp/api/app.md +++ b/docs-translations/jp/api/app.md @@ -431,6 +431,12 @@ dock アイコンを表示します。 アプリケーションの[dock menu][dock-menu]を設定します。 +### `app.dock.setIcon(image)` _OS X_ + +* `image` [NativeImage](native-image.md) + +dock アイコンに紐づいた`image`を設定します。 + [dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103 [tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx diff --git a/docs-translations/jp/api/environment-variables.md b/docs-translations/jp/api/environment-variables.md index 39fd8f80e0f9..f5277f146591 100644 --- a/docs-translations/jp/api/environment-variables.md +++ b/docs-translations/jp/api/environment-variables.md @@ -24,6 +24,11 @@ Windows コンソール上: Chromeのインターナルログをコンソールに出力します。 + +## `ELECTRON_LOG_ASAR_READS` + +ASARファイルからElectronが読み込んだとき、システム`tmpdir`へ読み込みオフセットとファイルのパスを記録します。ファイルの順序を最適化するために、得られたファイルはASARモジュールに提供されます。 + ## `ELECTRON_ENABLE_STACK_DUMPING` Electronがクラッシュしたとき、コンソールにスタックとレースを出力します。 diff --git a/docs-translations/jp/api/protocol.md b/docs-translations/jp/api/protocol.md index 841c64512a77..9f341b2f9742 100644 --- a/docs-translations/jp/api/protocol.md +++ b/docs-translations/jp/api/protocol.md @@ -45,9 +45,22 @@ app.on('ready', function() { レスポンスとしてファイルを送信する`scheme`のプロトコルを登録します。`scheme`で`request`が生成された時、`handler`は`handler(request, callback)`で呼び出されます。`scheme` 登録が成功したり、`completion(error)`が失敗したときに、`completion` は`completion(null)`で呼び出されます。 +* `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` Array (オプション) +* `callback` Function + +`uploadData` は `data` オブジェクトの配列です: + +* `data` Object + * `bytes` Buffer - 送信するコンテンツ + * `file` String - アップロードするファイルパス + `request`をハンドルするために、`callback`はファイルパスまたは`path`プロパティを持つオブジェクトで呼び出すべきです。例えば、`callback(filePath)` または`callback({path: filePath})`です。 -何もなし、数字、`error`プロパティを持つオブジェクトで、`callback`が呼び出された時、 `request`は指定した`error`番号で失敗します。使用できる提供されているエラー番号は、[net error list](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)を参照してください。 +何もなし、数字、`error`プロパティを持つオブジェクトで、`callback`が呼び出された時、 `request`は指定した`error`番号で失敗します。使用できる提供されているエラー番号は、[net error list][net-error]を参照してください。 既定では、`scheme`は、`file:`のような一般的なURIの構文に続くプロトコルと違う解析がされ、`http:`のように扱われます。なので、恐らく標準的なスキーマーのように扱われるスキーマーを持つために、`protocol.registerStandardSchemes` を呼び出したくなります。 @@ -57,7 +70,9 @@ app.on('ready', function() { * `handler` Function * `completion` Function (optional) -レスポンスとして`Buffer`を送信する`scheme`プロトコルを登録します。`callback`は、`Buffer`オブジェクトまたは`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があります。 +レスポンスとして`Buffer`を送信する`scheme`プロトコルを登録します。 + + `callback`は、`Buffer`オブジェクトまたは、`data`と`mimeType`、 `charset`プロパティを持つオブジェクトのどちらかで呼ばれる必要があることを除いて、この使用方法は、`registerFileProtocol`と同じです。 例: @@ -76,7 +91,9 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -レスポンスとして`String`を送信する`scheme`プロトコルを登録します。`callback`は、`String`または`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があります。 +レスポンスとして`String`を送信する`scheme`プロトコルを登録します。 + +`callback`は、`String`または`data`と `mimeType`、`chart`プロパティを持つオブジェクトを呼び出す必要があることを除いて、使用方法は`registerFileProtocol`と同じです。 ### `protocol.registerHttpProtocol(scheme, handler[, completion])` @@ -84,14 +101,22 @@ protocol.registerBufferProtocol('atom', function(request, callback) { * `handler` Function * `completion` Function (optional) -レスポンスとしてHTTPリクエストを送信する`scheme`プロトコルを登録します。`callback`は、`url`と`method`、`referrer`、`uploadData`、`session`プロパティを持つオブジェクトを呼び出す必要があります。 +レスポンスとしてHTTPリクエストを送信する`scheme`プロトコルを登録します。 + +`callback`は、`url`と`method`、`referrer`、`uploadData`、`session`プロパティを持つオブジェクトを呼び出す必要があることを除いて、使用方法は`registerFileProtocol`と同じです。 + +* `redirectRequest` Object + * `url` String + * `method` String + * `session` Object (オプション) + * `uploadData` Object (オプション) 既定では、HTTPリクエストは現在のセッションを再利用します。別のセッションでリクエストをしたい場合、`session` に `null`を設定する必要があります。 POSTリクエストは`uploadData`オブジェクトを提供する必要があります。 * `uploadData` object * `contentType` String - コンテンツのMIMEタイプ - * `data` String - 送信されるコンテンツ + * `data` String - 送信されるコンテンツ ### `protocol.unregisterProtocol(scheme[, completion])` @@ -139,12 +164,12 @@ POSTリクエストは`uploadData`オブジェクトを提供する必要があ `scheme`プロトコルをインターセプタ―し、レスポンスとして新しいHTTPリクエストを送信するプロトコルの新しいハンドラーとして`handler`を使います。 -Intercepts `scheme` protocol and uses `handler` as the protocol's new handler -which sends a new HTTP request as a response. - ### `protocol.uninterceptProtocol(scheme[, completion])` * `scheme` String * `completion` Function インターセプタ―したインストールされた`scheme`を削除し、オリジナルハンドラーをリストアします。 + + +[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h diff --git a/docs-translations/jp/api/session.md b/docs-translations/jp/api/session.md index 9385ac3e891e..a5d47d404a6d 100644 --- a/docs-translations/jp/api/session.md +++ b/docs-translations/jp/api/session.md @@ -197,6 +197,7 @@ proxyURL = ["://"][":"] ``` 具体例: + * `http=foopy:80;ftp=foopy2` - `http://`URLは`foopy:80`HTTPプロキシを使用し、`ftp://`URLは`foopy2:80` HTTPプロキシを使用します。 * `foopy:80` - 全てのURLで`foopy:80`を使用します。 * `foopy:80,bar,direct://` - 全てのURLで`foopy:80`HTTPプロキシを使用し、`foopy:80`が提供されていなければ`bar`を使用し、さらに使えない場合はプロキシを使いません。 @@ -296,6 +297,14 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details, * `method` String * `resourceType` String * `timestamp` Double + * `uploadData` Array (オプション) + * `callback` Function + +`uploadData`は `data`オブジェクトの配列です。 + +* `data` Object + * `bytes` Buffer - 送信されるコンテンツ + * `file` String - アップロードされるファイルパス `callback`は`response`オブジェクトでコールされる必要があります: @@ -317,6 +326,7 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, function(details, * `resourceType` String * `timestamp` Double * `requestHeaders` Object +* `callback` Function The `callback` has to be called with an `response` object: @@ -355,6 +365,7 @@ The `callback` has to be called with an `response` object: * `statusLine` String * `statusCode` Integer * `responseHeaders` Object +* `callback` Function `callback`は`response`オブジェクトでコールされる必要があります: diff --git a/docs-translations/jp/api/synopsis.md b/docs-translations/jp/api/synopsis.md index a2f701807ea0..683f5611eb12 100644 --- a/docs-translations/jp/api/synopsis.md +++ b/docs-translations/jp/api/synopsis.md @@ -4,7 +4,7 @@ Electron では全ての [Node.js のビルトインモジュール](http://node Electron はネイティブのデスクトップアプリケーション開発のための幾つかの追加のビルトインモジュールも提供しています。メインプロセスでだけ使えるモジュールもあれば、レンダラプロセス(ウェブページ)でだけ使えるモジュール、あるいはメインプロセス、レンダラプロセスどちらでも使えるモジュールもあります。 -基本的なルールは:[GUI][gui]、または低レベルのシステムに関連するモジュールはメインモジュールでだけ利用できるべきです。これらのモジュールを使用できるようにするためには [メインプロセス対レンダラプロセス][main-process] スクリプトの概念を理解する必要があります。 +基本的なルールは:[GUI][gui]、または低レベルのシステムに関連するモジュールはメインモジュールでだけ利用できるべきです。これらのモジュールを使用できるようにするためには [メインプロセス対レンダラプロセス](../tutorial/quick-start.md#メインプロセス)スクリプトの概念を理解する必要があります。 メインプロセススクリプトは普通の Node.js スクリプトのようなものです: @@ -64,6 +64,5 @@ require('electron').hideInternalModules() ``` [gui]: https://en.wikipedia.org/wiki/Graphical_user_interface -[main-process]: ../tutorial/quick-start.md#メインプロセス [desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment [issue-387]: https://github.com/atom/electron/issues/387 diff --git a/docs-translations/jp/faq/electron-faq.md b/docs-translations/jp/faq/electron-faq.md index b73831974772..c8a652277174 100644 --- a/docs-translations/jp/faq/electron-faq.md +++ b/docs-translations/jp/faq/electron-faq.md @@ -69,5 +69,38 @@ delete window.module; ``` +## `require('electron').xxx` は定義されていません。 + +Electronの組み込みモジュールを使うとに、次のようなエラーに遭遇するかもしれません。 + +``` +> require('electron').webFrame.setZoomFactor(1.0); +Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined +``` + +これは、ローカルまたはグローバルのどちらかで [npm `electron` module][electron-module] をインストールしたことが原因で、Electronの組み込みモジュールを上書きしてしまいます。 + +正しい組み込みモジュールを使用しているかを確認するために、`electron`モジュールのパスを出力します。 + +```javascript +console.log(require.resolve('electron')); +``` + +そして、次の形式かどうかを確認します。 + +``` +"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" +``` + +If it is something like もし、`node_modules/electron/index.js` のような形式の場合は、npm `electron` モジュールを削除するか、それをリネームします。 + +```bash +npm uninstall electron +npm uninstall -g electron +``` + +しかし、組み込みモジュールを使用しているのに、まだこのエラーが出る場合、不適切なプロセスでモジュールを使用しようとしている可能性が高いです。例えば、`electron.app`はメインプロセスのみで使え、一方で`electron.webFrame`はレンダラープロセスのみに提供されています。 + [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx +[electron-module]: https://www.npmjs.com/package/electron diff --git a/docs-translations/jp/tutorial/application-distribution.md b/docs-translations/jp/tutorial/application-distribution.md index 96dce25134aa..f05b098514b9 100644 --- a/docs-translations/jp/tutorial/application-distribution.md +++ b/docs-translations/jp/tutorial/application-distribution.md @@ -51,8 +51,8 @@ Electronにバンドルした後、ユーザーに配布する前に、 Electron ### Windows -`electron.exe`を任意の名前に変更でき、[rcedit](https://github.com/atom/rcedit) または -[ResEdit](http://www.resedit.net)のようなツールでアイコンやその他の情報を編集できます。 +`electron.exe`を任意の名前に変更でき、[rcedit](https://github.com/atom/rcedit) +のようなツールでアイコンやその他の情報を編集できます。 ### OS X diff --git a/docs-translations/jp/tutorial/debugging-main-process.md b/docs-translations/jp/tutorial/debugging-main-process.md index 0839d351598a..ffffdeb83ac5 100644 --- a/docs-translations/jp/tutorial/debugging-main-process.md +++ b/docs-translations/jp/tutorial/debugging-main-process.md @@ -55,13 +55,13 @@ $ electron --debug=5858 your/app $ electron --debug-brk=5858 your/app ``` -### 5. Electronを使用して、[node-inspector][node-inspector] サーバーを開始する +### 6. Electronを使用して、[node-inspector][node-inspector] サーバーを開始する ```bash $ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js ``` -### 6. デバッグUIを読み込みます +### 7. デバッグUIを読み込みます Chromeブラウザで、 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 を開きます。エントリーラインを見るために、debug-brkを始めるには、ポーズをクリックします。 diff --git a/docs-translations/jp/tutorial/desktop-environment-integration.md b/docs-translations/jp/tutorial/desktop-environment-integration.md index 24d3e9d2aaa7..0ef44b2f47c7 100644 --- a/docs-translations/jp/tutorial/desktop-environment-integration.md +++ b/docs-translations/jp/tutorial/desktop-environment-integration.md @@ -25,16 +25,7 @@ myNotification.onclick = function () { * Windows 10では、通知はすぐに動作します。 * Windows 8.1 と Windows 8では、[Application User Model ID][app-user-model-id]で、アプリへのショートカットはスタートメニューにインストールされます。しかし、スタートメニューにピン止めをする必要がありません。 -* Windows 7以前は、通知はサポートされていません。 しかし、[Tray API](tray-balloon)を使用してバルーンヒントを送信することができます。 - -通知にイメージを使うために、通知オプションの `icon` プロパティにローカルのイメージファイル(`png`が望ましい)を設定します。 正しくない、または`http/https`の URLを設定した場合でも、通知は表示されますが、イメージは表示されません。 - -```javascript -new Notification('Title', { - body: 'Notification with icon', - icon: 'file:///C:/Users/feriese/Desktop/icon.png' -}); -``` +* Windows 7以前は、通知はサポートされていません。 しかし、[Tray API][tray-balloon]を使用してバルーンヒントを送信することができます。 その上で、bodyの最大サイズは250文字であることに留意してください。Windowsチームは、通知は200文字にすることを推奨しています。 diff --git a/docs-translations/jp/tutorial/mac-app-store-submission-guide.md b/docs-translations/jp/tutorial/mac-app-store-submission-guide.md index b2cf9d26d30d..47d7a76b925b 100644 --- a/docs-translations/jp/tutorial/mac-app-store-submission-guide.md +++ b/docs-translations/jp/tutorial/mac-app-store-submission-guide.md @@ -2,6 +2,8 @@ v0.34.0から、ElectronはMac App Store (MAS)にパッケージ化したアプリを登録することができます。このガイドでは、MASビルド用の制限とアプリを登録する方法についての情報を提供します。 +__Note:__ v0.36.0から、アプリがサンドボックス化された後GPUプロセスを妨害するバグがあるので、このバグが修正されるまでは、v0.35.xを使用することを推奨します。[issue #3871][issue-3871]で、このことに関する追加情報を確認できます。 + __Note:__ Mac App Storeにアプリを登録するには、費用が発生する[Apple Developer Program][developer-program]に登録する必要があります。 ## アプリを登録する方法 @@ -63,13 +65,18 @@ INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libnode.dylib" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Electron Framework" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" -codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" +if [ -d "$FRAMEWORKS_PATH/Squirrel.framework/Versions/A" ]; then + # Signing a non-MAS build. + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Mantle.framework/Versions/A" + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/ReactiveCocoa.framework/Versions/A" + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Squirrel.framework/Versions/A" +fi +codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" + productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" ``` @@ -83,8 +90,8 @@ OS Xで、サンドボックスにアプリを新しく追加した場合、基 アプリのサンドボックスですべての要件を満たすために、MASビルドで次のモジュールを無効にしてください。 -* `crash-reporter` -* `auto-updater` +* `crashReporter` +* `autoUpdater` 次の挙動を変更してください。 @@ -92,7 +99,39 @@ OS Xで、サンドボックスにアプリを新しく追加した場合、基 * 一部のアクセシビリティ機能が動作しないことがあります。 * アプリはDNSの変更を認識しません。 -アプリのサンドボックスでの使用が原因で、アプリがアクセスできるリソースは厳密に制限されています。詳細は、 [App Sandboxing][app-sandboxing] を参照してください。 +アプリのサンドボックスでの使用では、アプリがアクセスできるリソースは厳密に制限されています。詳細は、 [App Sandboxing][app-sandboxing] を参照してください。 + +## Electronが使用する暗号化アルゴリズム + +あなたが住んでいる国や地域に依存して、Mac App Store がアプリで使用する暗号化アルゴリズムを文章化することを要求することがあり、暗号登録番号(U.S. Encryption Registration (ERN))の同意のコピーの提出を求められます。 + +Electron は次の暗号アルゴリズムを使用しています: + +* AES - [NIST SP 800-38A](http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf), [NIST SP 800-38D](http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf), [RFC 3394](http://www.ietf.org/rfc/rfc3394.txt) +* HMAC - [FIPS 198-1](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf) +* ECDSA - ANS X9.62–2005 +* ECDH - ANS X9.63–2001 +* HKDF - [NIST SP 800-56C](http://csrc.nist.gov/publications/nistpubs/800-56C/SP-800-56C.pdf) +* PBKDF2 - [RFC 2898](https://tools.ietf.org/html/rfc2898) +* RSA - [RFC 3447](http://www.ietf.org/rfc/rfc3447) +* SHA - [FIPS 180-4](http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf) +* Blowfish - https://www.schneier.com/cryptography/blowfish/ +* CAST - [RFC 2144](https://tools.ietf.org/html/rfc2144), [RFC 2612](https://tools.ietf.org/html/rfc2612) +* DES - [FIPS 46-3](http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf) +* DH - [RFC 2631](https://tools.ietf.org/html/rfc2631) +* DSA - [ANSI X9.30](http://webstore.ansi.org/RecordDetail.aspx?sku=ANSI+X9.30-1%3A1997) +* EC - [SEC 1](http://www.secg.org/sec1-v2.pdf) +* IDEA - "On the Design and Security of Block Ciphers" book by X. Lai +* MD2 - [RFC 1319](http://tools.ietf.org/html/rfc1319) +* MD4 - [RFC 6150](https://tools.ietf.org/html/rfc6150) +* MD5 - [RFC 1321](https://tools.ietf.org/html/rfc1321) +* MDC2 - [ISO/IEC 10118-2](https://www.openssl.org/docs/manmaster/crypto/mdc2.html) +* RC2 - [RFC 2268](https://tools.ietf.org/html/rfc2268) +* RC4 - [RFC 4345](https://tools.ietf.org/html/rfc4345) +* RC5 - http://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf +* RIPEMD - [ISO/IEC 10118-3](http://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004) + +ERNの同意を取得するには、 [How to legally submit an app to Apple’s App Store when it uses encryption (or how to obtain an ERN)][ern-tutorial]を参照してくだsだい。 [developer-program]: https://developer.apple.com/support/compare-memberships/ [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html @@ -101,3 +140,5 @@ OS Xで、サンドボックスにアプリを新しく追加した場合、基 [create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html [submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html [app-sandboxing]: https://developer.apple.com/app-sandboxing/ +[issue-3871]: https://github.com/atom/electron/issues/3871 +[ern-tutorial]: https://carouselapps.com/2015/12/15/legally-submit-app-apples-app-store-uses-encryption-obtain-ern/ diff --git a/docs-translations/jp/tutorial/supported-platforms.md b/docs-translations/jp/tutorial/supported-platforms.md index 8482931ed21e..7d9f24b7ab6b 100644 --- a/docs-translations/jp/tutorial/supported-platforms.md +++ b/docs-translations/jp/tutorial/supported-platforms.md @@ -4,7 +4,7 @@ Electronでは次のプラットフォームをサポートします。 ### OS X -OS X用に提供しているバイナリは64bitのみで、サポートするOS Xのバージョンは、OS X 10.8 以降です。 +OS X用に提供しているバイナリは64bitのみで、サポートするOS Xのバージョンは、OS X 10.9 以降です。 ### Windows diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index cfcd4ee3aab8..ec4cb74c253a 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -252,6 +252,14 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입 `beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우 종료가 취소 될 수 있습니다. +### `app.hide()` _OS X_ + +최소화를 하지 않고 어플리케이션의 모든 윈도우들을 숨깁니다. + +### `app.show()` _OS X_ + +숨긴 어플리케이션 윈도우들을 다시 보이게 만듭니다. 자동으로 포커스되지 않습니다. + ### `app.exit(exitCode)` * `exitCode` Integer diff --git a/docs-translations/ko-KR/api/menu.md b/docs-translations/ko-KR/api/menu.md index a2d5b8d7a63c..347ea880dce0 100644 --- a/docs-translations/ko-KR/api/menu.md +++ b/docs-translations/ko-KR/api/menu.md @@ -293,6 +293,11 @@ OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번 이름이 됩니다. 어플리케이션 이름을 변경하려면 앱 번들내의 `Info.plist` 파일을 수정해야 합니다. 자세한 내용은 [About Information Property List Files][AboutInformationPropertyListFiles] 문서를 참고하세요. +## 지정한 브라우저 윈도우에 메뉴 설정 (*Linux* *Windows*) + +브라우저 윈도우의 [`setMenu` 메서드][setMenu]는 어떤 브라우저 윈도우의 메뉴를 설정할 +수 있습니다. + ## 메뉴 아이템 위치 `Menu.buildFromTemplate`로 메뉴를 만들 때 `position`과 `id`를 사용해서 아이템의 @@ -367,3 +372,4 @@ OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번 ``` [AboutInformationPropertyListFiles]: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html +[setMenu]: https://github.com/atom/electron/blob/master/docs/api/browser-window.md#winsetmenumenu-linux-windows diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 6f39ab9dcdd4..59eceb05a7a3 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -212,6 +212,7 @@ proxyURL = ["://"][":"] ``` 예시: + * `http=foopy:80;ftp=foopy2` - http:// URL에 `foopy:80` HTTP 프록시를 사용합니다. `foopy2:80` 는 ftp:// URL에 사용됩니다. * `foopy:80` - 모든 URL에 `foopy:80` 프록시를 사용합니다. @@ -287,6 +288,30 @@ myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, c callback(false); }); ``` +#### `ses.setPermissionRequestHandler(handler)` + +* `handler` Function + * `webContents` Object - [WebContents](web-contents.md) 권한을 요청. + * `permission` String - 'media', 'geolocation', 'notifications', + 'midiSysex'의 나열. + * `callback` Function - 권한 허용 및 거부. + +`session`의 권한 요청에 응답을 하는데 사용하는 핸들러를 설정합니다. +`callback('granted')`를 호출하면 권한 제공을 허용하고 `callback('denied')`를 +호출하면 권한 제공을 거부합니다. + +```javascript +session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) { + if (webContents.getURL() === host) { + if (permission == "notifications") { + callback(); // 거부됨. + return; + } + } + + callback('granted'); +}); +``` #### `ses.webRequest` diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 4d688a40944f..3f9a7daaaa76 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -278,6 +278,28 @@ Returns: ``` +### Event: 'cursor-changed' + +Returns: + +* `event` Event +* `type` String +* `image` NativeImage (optional) +* `scale` Float (optional) + +커서 타입이 변경될 때 발생하는 이벤트입니다. `type` 매개변수는 다음 값이 될 수 있습니다: +`default`, `crosshair`, `pointer`, `text`, `wait`, `help`, `e-resize`, `n-resize`, +`ne-resize`, `nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`, +`ns-resize`, `ew-resize`, `nesw-resize`, `nwse-resize`, `col-resize`, +`row-resize`, `m-panning`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`, +`s-panning`, `se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`, +`cell`, `context-menu`, `alias`, `progress`, `nodrop`, `copy`, `none`, +`not-allowed`, `zoom-in`, `zoom-out`, `grab`, `grabbing`, `custom`. + +만약 `type` 매개변수가 `custom` 이고 `image` 매개변수가 `NativeImage`를 통한 커스텀 +커서를 지정했을 때, 해당 이미지로 커서가 변경됩니다. 또한 `scale` 매개변수는 이미지의 +크기를 조정합니다. + ## Instance Methods `webContents`객체는 다음과 같은 인스턴스 메서드들을 가지고 있습니다. diff --git a/docs-translations/ko-KR/tutorial/application-distribution.md b/docs-translations/ko-KR/tutorial/application-distribution.md index 34eb8cee71f7..635337574152 100644 --- a/docs-translations/ko-KR/tutorial/application-distribution.md +++ b/docs-translations/ko-KR/tutorial/application-distribution.md @@ -60,8 +60,8 @@ electron/resources/ ### Windows `electron.exe`을 원하는 이름으로 변경할 수 있습니다. -그리고 [rcedit](https://github.com/atom/rcedit) 또는 -[ResEdit](http://www.resedit.net)를 사용하여 아이콘을 변경할 수 있습니다. +그리고 [rcedit](https://github.com/atom/rcedit) +를 사용하여 아이콘을 변경할 수 있습니다. ### OS X diff --git a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md index d316d16da83f..c319f344b638 100644 --- a/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md +++ b/docs-translations/ko-KR/tutorial/mac-app-store-submission-guide.md @@ -4,6 +4,10 @@ Electron은 v0.34.0 버전부터 앱 패키지를 Mac App Store(MAS)에 제출 되었습니다. 이 가이드는 어플리케이션을 앱 스토어에 등록하는 방법과 빌드의 한계에 대한 설명을 제공합니다. +__참고:__ v0.36.0 버전부터 어플리케이션이 샌드박스화 된 상태로 실행되면 GPU 작동을 +방지하는 버그가 있었습니다. 따라서 이 버그가 고쳐지기 전까진 v0.35.x 버전을 사용하는 +것을 권장합니다. 이 버그에 관한 자세한 사항은 [issue #3871][issue-3871]를 참고하세요. + __참고:__ Mac App Store에 어플리케이션을 등록하려면 [Apple Developer Program][developer-program]에 등록되어 있어야 하며 비용이 발생할 수 있습니다. @@ -73,13 +77,18 @@ INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libnode.dylib" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Electron Framework" -codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/" +codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" -codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" +if [ -d "$FRAMEWORKS_PATH/Squirrel.framework/Versions/A" ]; then + # non-MAS 빌드 서명 + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Mantle.framework/Versions/A" + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/ReactiveCocoa.framework/Versions/A" + codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Squirrel.framework/Versions/A" +fi +codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" + productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" ``` @@ -98,8 +107,8 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES 모든 어플리케이션 샌드박스에 대한 요구 사항을 충족시키기 위해, 다음 모듈들은 MAS 빌드에서 비활성화됩니다: -* `crash-reporter` -* `auto-updater` +* `crashReporter` +* `autoUpdater` 그리고 다음 동작으로 대체됩니다: @@ -111,7 +120,42 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES 엄격하게 제한되어 있습니다. 자세한 내용은 [App Sandboxing][app-sandboxing] 문서를 참고하세요. -**역주:** [Mac 앱 배포 가이드 공식 문서](https://developer.apple.com/osx/distribution/kr/) +## Electron에서 사용하는 암호화 알고리즘 + +국가와 살고 있는 지역에 따라, 맥 앱스토어는 제출한 어플리케이션에서 사용하는 암호화 +알고리즘의 문서를 요구할 수 있습니다. 심지어 U.S. Encryption Registration (ERN)의 +승인 사본을 제출하라고 할 수도 있습니다. + +Electron은 다음과 같은 암호화 알고리즘을 사용합니다: + +* AES - [NIST SP 800-38A](http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf), [NIST SP 800-38D](http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf), [RFC 3394](http://www.ietf.org/rfc/rfc3394.txt) +* HMAC - [FIPS 198-1](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf) +* ECDSA - ANS X9.62–2005 +* ECDH - ANS X9.63–2001 +* HKDF - [NIST SP 800-56C](http://csrc.nist.gov/publications/nistpubs/800-56C/SP-800-56C.pdf) +* PBKDF2 - [RFC 2898](https://tools.ietf.org/html/rfc2898) +* RSA - [RFC 3447](http://www.ietf.org/rfc/rfc3447) +* SHA - [FIPS 180-4](http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf) +* Blowfish - https://www.schneier.com/cryptography/blowfish/ +* CAST - [RFC 2144](https://tools.ietf.org/html/rfc2144), [RFC 2612](https://tools.ietf.org/html/rfc2612) +* DES - [FIPS 46-3](http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf) +* DH - [RFC 2631](https://tools.ietf.org/html/rfc2631) +* DSA - [ANSI X9.30](http://webstore.ansi.org/RecordDetail.aspx?sku=ANSI+X9.30-1%3A1997) +* EC - [SEC 1](http://www.secg.org/sec1-v2.pdf) +* IDEA - "On the Design and Security of Block Ciphers" book by X. Lai +* MD2 - [RFC 1319](http://tools.ietf.org/html/rfc1319) +* MD4 - [RFC 6150](https://tools.ietf.org/html/rfc6150) +* MD5 - [RFC 1321](https://tools.ietf.org/html/rfc1321) +* MDC2 - [ISO/IEC 10118-2](https://www.openssl.org/docs/manmaster/crypto/mdc2.html) +* RC2 - [RFC 2268](https://tools.ietf.org/html/rfc2268) +* RC4 - [RFC 4345](https://tools.ietf.org/html/rfc4345) +* RC5 - http://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf +* RIPEMD - [ISO/IEC 10118-3](http://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004) + +ERN의 승인을 얻는 방법은, 다음 글을 참고하는 것이 좋습니다: +[어플리케이션이 암호화를 사용할 때, 합법적으로 Apple의 앱 스토어에 제출하는 방법 (또는 ERN의 승인을 얻는 방법)][ern-tutorial]. + +**역주:** [Mac 앱 배포 가이드 공식 한국어 문서](https://developer.apple.com/osx/distribution/kr/) [developer-program]: https://developer.apple.com/support/compare-memberships/ [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html @@ -120,3 +164,5 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES [create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html [submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html [app-sandboxing]: https://developer.apple.com/app-sandboxing/ +[issue-3871]: https://github.com/atom/electron/issues/3871 +[ern-tutorial]: https://carouselapps.com/2015/12/15/legally-submit-app-apples-app-store-uses-encryption-obtain-ern/ diff --git a/docs-translations/ko-KR/tutorial/supported-platforms.md b/docs-translations/ko-KR/tutorial/supported-platforms.md index 3b3a00d72156..656d31308e07 100644 --- a/docs-translations/ko-KR/tutorial/supported-platforms.md +++ b/docs-translations/ko-KR/tutorial/supported-platforms.md @@ -4,7 +4,7 @@ Electron에선 다음과 같은 플랫폼을 지원합니다: ### OS X -OS X는 64비트 바이너리만 제공됩니다. 그리고 최소 OS X 지원 버전은 10.8입니다. +OS X는 64비트 바이너리만 제공됩니다. 그리고 최소 OS X 지원 버전은 10.9입니다. ### Windows diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index f458e51da8f3..05fedfeb4381 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -6,9 +6,14 @@ documentação na lista de [versões disponíveis](http://electron.atom.io/docs/ ou se você estiver usando a interface do GitHub, abra o *dropdown* "Switch branches/tags" e selecione a *tag* que corresponde à sua versão. +## FAQ + +Existem muitas perguntas comuns que são feitas, verifique antes de criar uma issue. +* [Electron FAQ](../../docs/faq/electron-faq.md) + ## Guias -* [Platformas Suportadas](../../tutorial/supported-platforms.md) +* [Plataformas Suportadas](tutorial/supported-platforms.md) * [Distribuição de Aplicações](tutorial/application-distribution.md) * [Guia de Submissão da Mac App Store](../../tutorial/mac-app-store-submission-guide.md) * [Empacotamento da Aplicação](tutorial/application-packaging.md) @@ -17,6 +22,7 @@ selecione a *tag* que corresponde à sua versão. * [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md) * [Extensão DevTools](../../docs/tutorial/devtools-extension.md) * [Usando o Plugin Pepper Flash](tutorial/using-pepper-flash-plugin.md) +* [Usando o Plugin Widevine CDM](../../tutorial/using-widevine-cdm-plugin.md) ## Tutoriais @@ -58,6 +64,7 @@ selecione a *tag* que corresponde à sua versão. ### Módulos para o Processo Renderizador: +* [DesktopCapturer](../../docs/api/desktop-capturer) * [ipcRenderer](../../docs/api/ipc-renderer.md) * [remote](../../docs/api/remote.md) * [webFrame](../../docs/api/web-frame.md) diff --git a/docs-translations/pt-BR/development/source-code-directory-structure.md b/docs-translations/pt-BR/development/source-code-directory-structure.md new file mode 100644 index 000000000000..77c01d79113e --- /dev/null +++ b/docs-translations/pt-BR/development/source-code-directory-structure.md @@ -0,0 +1,53 @@ +# Estrutura de Diretórios do Código-Fonte + +O código-fonte do Electron é separado em algumas partes, seguindo principalmente as convenções de separação do chromium. + +Você pode se familiarizar com a [arquitetura de multiprocessamento ](http://dev.chromium.org/developers/design-documents/multi-process-architecture) do Chromium para entender melhor o código-fonte. + + +## Estrutura do Código-Fonte + +``` +Electron +├──atom - Código fonte do Electron. +| ├── app - Código de inicialização. +| ├── browser - A interface incluíndo a janela principal, UI, e todas as coisas do processo principal. Ele se comunica com o renderizador para gerenciar as páginas web. +| |   ├── lib - Código Javascript para inicializar o processo principal. +| | ├── ui - Implementação da UI para plataformas distintas. +| | | ├── cocoa - Código-fonte específico do cocoa . +| | | ├── gtk - Código-font específico do GTK+. +| | | └── win - Código-fonte específico do Windows GUI. +| | ├── default_app - A página padrão é mostrada quando +| | | Electron inicializa sem fornecer um app. +| | ├── api - Implementação do processo principal das APIs +| | | └── lib - Código Javascript, parte da implementação da API. +| | ├── net - Código relacionado a rede. +| | ├── mac - Código fonte em Object-c, específico para Mac. +| | └── resources - Icones, arquivos dependentes da plataforma, etc. +| ├── renderer - Código que é executado no processo de renderização. +| | ├── lib - Parte do código Javascript de inicialização do renderizador. +| | └── api - Implementação das APIs para o processo de renderizaçãp. +| | └── lib - Código Javascript, parte da implementação da API. +| └── common - Código que utiliza ambos os processos, o principal e o de rendezição, +| ele inclui algumas funções utilitárias e códigos para integrar com ciclo de mensagens do node no ciclo de mensagens do Chromium. +| ├── lib - Código Javascript comum para a inicialização. +| └── api - A implementação de APIs comuns e fundamentação dos +| módulos integrados com Electron's. +| └── lib - Código Javascript, parte da implementação da API. +├── chromium_src - Código-fonte copiado do Chromium. +├── docs - Documentação. +├── spec - Testes Automáticos. +├── atom.gyp - Regras de compilação do Electron. +└── common.gypi - Configuração específica do compilador e regras de construção para outros componentes + como `node` e `breakpad`. +``` + +## Estrutura de Outros Diretórios. + +* **script** - Scripts utilizado para fins de desenvolvimento como building, packaging, testes, etc. +* **tools** - Scripts auxiliares, utilizados pelos arquivos gyp, ao contrário do`script`, os scripts colocados aqui nunca devem ser invocados diretamente pelos usuários. +* **vendor** - Dependências de código-fonte de terceiros, nós não utilizamos `third_party` como nome porque ele poderia ser confundido com o diretório homônimo existente no código-fonte do Chromium. +* **node_modules** - Módulos de terceiros em node usados para compilação +* **out** - Diretório temporário saída do `ninja`. +* **dist** - Diretório temporário do `script/create-dist.py` ao criar uma distribuição +* **external_binaries** - Binários baixados de Frameworks de terceiros que não suportam a compilação com `gyp`. diff --git a/docs-translations/pt-BR/tutorial/application-distribution.md b/docs-translations/pt-BR/tutorial/application-distribution.md index 41f2457c408b..f5a87d532c52 100644 --- a/docs-translations/pt-BR/tutorial/application-distribution.md +++ b/docs-translations/pt-BR/tutorial/application-distribution.md @@ -1,7 +1,7 @@ # Distribuição de aplicações -Para distribuir sua aplicação com o Electron, você deve nomear o diretório que contém sua aplicação como -`app` e dentro deste diretório colocar os recursos que você está utilizando (no OSX +Para distribuir sua aplicação com o Electron, você deve nomear o diretório que contém sua aplicação como +`app` e dentro deste diretório colocar os recursos que você está utilizando (no OSX `Electron.app/Contents/Resources/`, no Linux e no Windows é em `resources/`): @@ -24,7 +24,7 @@ electron/resources/app ``` Logo após execute `Electron.app` (ou `electron` no Linux e `electron.exe` no Windows), -e o Electron iniciaria a aplicação. O diretório `electron` será utilizado para criar a distribuição para +e o Electron iniciaria a aplicação. O diretório `electron` será utilizado para criar a distribuição para usuários finais. ## Empacotando sua aplicação em um arquivo. @@ -58,11 +58,10 @@ Mais detalhes podem ser encontrados em [Empacotamento da aplicação](../../../d Depois de empacotar seu aplicativo Electron, você vai querer renomear a marca Electron antes de distribuí-lo aos usuários. -### Janelas +### Windows Você pode renomear `electron.exe` para o nome que desejar e editar o seu ícone e outras -informações com ferramentas como [rcedit](https://github.com/atom/rcedit) ou -[ResEdit](http://www.resedit.net). +informações com ferramentas como [rcedit](https://github.com/atom/rcedit). ### OS X @@ -115,4 +114,4 @@ uma tarefa para o Grunt foi criado e irá cuidar desta tarefa automaticamente pa [grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell). Esta tarefa irá automaticamente editar o arquivo `.gyp`, compilar o código -e reconstruir os módulos nativos da aplicação para utilizar o novo nome. \ No newline at end of file +e reconstruir os módulos nativos da aplicação para utilizar o novo nome. diff --git a/docs-translations/pt-BR/tutorial/supported-platforms.md b/docs-translations/pt-BR/tutorial/supported-platforms.md new file mode 100644 index 000000000000..0fc42179bb9c --- /dev/null +++ b/docs-translations/pt-BR/tutorial/supported-platforms.md @@ -0,0 +1,22 @@ +# Plataformas Suportadas + +As plataformas suportadas por Electron são: + +### OS X + +Somente binarios em 64bit são construidos para OS X e a versão mínima suportada é OS X 10.9. + +### Windows +Suporte para Windows 7 ou superior, versões anteriores não são suportados (e não ira funcionar) + + Binarios em `x86` e `amd64` (x64) são construidos para Windows. Atencão: Versão `ARM` do Windows não é suportada agora. + +### Linux +Binario pré-construido `ia32`(`i686`) e binario `x64`(`amd64`) são construidas no Ubuntu 12.04, binario `arm` está construido contra ARM v7 com hard-float ABI e NEION para Debian Wheezy. + +Se o pré-compilador poderá ser executado por uma distribuição, depende se a distruibuicão inclui as blibliotecas que o Eletron está vinculando na plataforma de construcão, por este motivo apenas Ubuntu 12.04 é garantido para funcionar corretamente, mas as seguintes distribuições foram verificados com o pre-compilador: + + +* Ubuntu 12.04 ou superior +* Fedora 21 +* Debian 8 diff --git a/docs-translations/zh-CN/api/app.md b/docs-translations/zh-CN/api/app.md index 03eb083dfa6e..448a5a373e91 100644 --- a/docs-translations/zh-CN/api/app.md +++ b/docs-translations/zh-CN/api/app.md @@ -58,10 +58,14 @@ app.on('window-all-closed', function() { 和 `window-all-closed` 事件的区别。 ### 事件: 'quit' +返回: + +* `event` 事件 +* `exitCode` 整数 当应用程序正在退出时触发。 -### 事件: 'open-file' +### 事件: 'open-file' _OS X_ 返回: @@ -73,8 +77,8 @@ app.on('window-all-closed', function() { 请确认在应用启动的时候(甚至在 `ready` 事件被触发前)就对 `open-file` 事件进行监听,以处理这种情况。 如果你想处理这个事件,你应该调用 `event.preventDefault()` 。 - -### 事件: 'open-url' +在 Windows系统中, 你需要通过解析 process.argv 来获取文件路径。 +### 事件: 'open-url' _OS X_ 返回: @@ -121,32 +125,89 @@ app.on('window-all-closed', function() { 当一个 [浏览器窗口](browser-window.md) 被创建的时候触发。 -### 事件: 'select-certificate' - -当一个客户端认证被请求的时候被触发。 +### 事件: 'certificate-error' 返回: * `event` 事件 -* `webContents` [web组件](browser-window.md#class-webcontents) +* `webContents` [web组件](web-contents.md) * `url` 字符串 * `certificateList` 对象 * `data` PEM 编码数据 * `issuerName` 发行者的公有名称 * `callback` 函数 +Emitted when failed to verify the `certificate` for `url`, to trust the +certificate you should prevent the default behavior with +`event.preventDefault()` and call `callback(true)`. + +```javascript +session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { + if (url == "https://github.com") { + // Verification logic. + event.preventDefault(); + callback(true); + } else { + callback(false); + } +}); +``` + +### 事件: 'select-client-certificate' + + +返回: + +* `event` 事件 +* `webContents` [web组件](web-contents.md) +* `url` 字符串 +* `certificateList` 对象 + * `data` PEM 编码数据 + * `issuerName` 发行者的公有名称 +* `callback` 函数 + +当一个客户端认证被请求的时候被触发。 + +The `url` corresponds to the navigation entry requesting the client certificate +and `callback` needs to be called with an entry filtered from the list. +Using `event.preventDefault()` prevents the application from using the first +certificate from the store. ```javascript app.on('select-certificate', function(event, host, url, list, callback) { event.preventDefault(); callback(list[0]); }) ``` +### Event: 'login' -The `url` corresponds to the navigation entry requesting the client certificate -and `callback` needs to be called with an entry filtered from the list. -Using `event.preventDefault()` prevents the application from using the first -certificate from the store. +Returns: +* `event` Event +* `webContents` [Web组件](web-contents.md) +* `request` Object + * `method` String + * `url` URL + * `referrer` URL +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String +* `callback` Function + +当 `webContents` 要做验证时被触发。 + +The default behavior is to cancel all authentications, to override this you +should prevent the default behavior with `event.preventDefault()` and call +`callback(username, password)` with the credentials. + +```javascript +app.on('login', function(event, webContents, request, authInfo, callback) { + event.preventDefault(); + callback('username', 'secret'); +}) +``` ### 事件: 'gpu-process-crashed' 当GPU进程崩溃时触发。 @@ -164,6 +225,23 @@ certificate from the store. 这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。会存在一个窗口被 `beforeunload` 事件处理器返回 `false` 取消退出的可能性。 +### `app.hide()` _OS X_ + +隐藏所有的应用窗口,不是最小化. + +### `app.show()` _OS X_ + +隐藏后重新显示所有的窗口,不会自动选中他们。 + +### `app.exit(exitCode)` + +* `exitCode` 整数 + +带着`exitCode`退出应用. + +所有的窗口会被立刻关闭,不会询问用户。`before-quit` 和 `will-quit` 这2个事件不会被触发 + + ### `app.getAppPath()` 返回当前应用所在的文件路径。 @@ -182,15 +260,15 @@ certificate from the store. * `$XDG_CONFIG_HOME` or `~/.config` Linux 中 * `~/Library/Application Support` OS X 中 * `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称。 -* `cache` 所有用户应用程序缓存的文件夹,默认对应: - * `%APPDATA%` Windows 中 (没有一个通用的缓存位置) - * `$XDG_CACHE_HOME` 或 `~/.cache` Linux 中 - * `~/Library/Caches` OS X 中 -* `userCache` 用于存放应用程序缓存的文件夹,默认是 `cache` 文件夹附加应用的名称。 * `temp` 临时文件夹。 -* `userDesktop` 当前用户的桌面文件夹。 -* `exe` 当前的可执行文件。 -* `module` `libchromiumcontent` 库。 +* `exe` 当前的可执行文件 +* `module` `libchromiumcontent` 库. +* `desktop` 当前用户的桌面文件夹。 +* `documents` "我的文件夹"的路径. +* `downloads` 用户下载目录的路径. +* `music` 用户音乐目录的路径. +* `pictures` 用户图片目录的路径. +* `videos` 用户视频目录的路径. ### `app.setPath(name, path)` @@ -201,7 +279,7 @@ certificate from the store. 如果这个路径指向的文件夹不存在,这个文件夹将会被这个方法创建。 如果错误则抛出 `Error` 。 -你只可以指向 `app.getPath` 中定义过 `name` 的路径。You can only override paths of a `name` defined in `app.getPath`. +你只可以指向 `app.getPath` 中定义过 `name` 的路径。 默认情况下,网页的 cookie 和缓存都会储存在 `userData` 文件夹。 如果你想要改变这个位置,你需要在 `app` 模块中的 `ready` 事件被触发之前重写 `userData` 的路径。 @@ -220,16 +298,11 @@ certificate from the store. ### `app.getLocale()` -返回当前应用程序的位置。 +返回当前应用程序的语言种类。 -### `app.resolveProxy(url, callback)` -* `url` URL -* `callback` 函数 -为 `url` 解析代理信息。 `callback` 在请求被执行之后将会被 `callback(proxy)` 调用。 - -### `app.addRecentDocument(path)` +### `app.addRecentDocument(path)` _OS X_ _Windows_ * `path` 字符串 @@ -237,7 +310,7 @@ certificate from the store. 这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过dock 菜单进行访问。 -### `app.clearRecentDocuments()` +### `app.clearRecentDocuments()` _OS X_ _Windows_ 清除最近访问的文档列表。 @@ -257,6 +330,103 @@ certificate from the store. * `iconPath` 字符串 - JumpList 中显示的 icon 的绝对路径,可以是一个任意包含一个icon的资源文件。你通常可以通过指明 `process.execPath` 来显示程序中的icon。 * `iconIndex` 整数 - icon文件中的icon目录。如果一个icon文件包括了两个或多个icon,就需要设置这个值以确定icon。如果一个文件仅包含一个icon,那么这个值为0。 +### `app.allowNTLMCredentialsForAllDomains(allow)` + +* `allow` Boolean + +Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate +authentication - normally, Electron will only send NTLM/Kerberos credentials for +URLs that fall under "Local Intranet" sites (i.e. are in the same domain as you). +However, this detection often fails when corporate networks are badly configured, +so this lets you co-opt this behavior and enable it for all URLs. +### `app.makeSingleInstance(callback)` + +* `callback` Function + +This method makes your application a Single Instance Application - instead of +allowing multiple instances of your app to run, this will ensure that only a +single instance of your app is running, and other instances signal this +instance and exit. + +`callback` will be called with `callback(argv, workingDirectory)` when a second +instance has been executed. `argv` is an Array of the second instance's command +line arguments, and `workingDirectory` is its current working directory. Usually +applications respond to this by making their primary window focused and +non-minimized. + +The `callback` is guaranteed to be executed after the `ready` event of `app` +gets emitted. + +This method returns `false` if your process is the primary instance of the +application and your app should continue loading. And returns `true` if your +process has sent its parameters to another instance, and you should immediately +quit. + +On OS X the system enforces single instance automatically when users try to open +a second instance of your app in Finder, and the `open-file` and `open-url` +events will be emitted for that. However when users start your app in command +line the system's single instance machanism will be bypassed and you have to +use this method to ensure single instance. + +An example of activating the window of primary instance when a second instance +starts: + +```js +var myWindow = null; + +var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { + // Someone tried to run a second instance, we should focus our window. + if (myWindow) { + if (myWindow.isMinimized()) myWindow.restore(); + myWindow.focus(); + } + return true; +}); + +if (shouldQuit) { + app.quit(); + return; +} + +// Create myWindow, load the rest of the app, etc... +app.on('ready', function() { +}); +``` +### `app.setAppUserModelId(id)` _Windows_ + +* `id` String + +改变 [Application User Model ID][app-user-model-id] 的 `id`. + +### `app.isAeroGlassEnabled()` _Windows_ + +This method returns `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx) +(Aero Glass) is enabled, and `false` otherwise. You can use it to determine if +you should create a transparent window or not (transparent windows won't work +correctly when DWM composition is disabled). + +Usage example: + +```js +let browserOptions = {width: 1000, height: 800}; + +// Make the window transparent only if the platform supports it. +if (process.platform !== 'win32' || app.isAeroGlassEnabled()) { + browserOptions.transparent = true; + browserOptions.frame = false; +} + +// Create the window. +win = new BrowserWindow(browserOptions); + +// Navigate. +if (browserOptions.transparent) { + win.loadURL('file://' + __dirname + '/index.html'); +} else { + // No transparency, so we load a fallback that uses basic styles. + win.loadURL('file://' + __dirname + '/fallback.html'); +} +``` ### `app.commandLine.appendSwitch(switch[, value])` 通过可选的参数 `value` 给 Chromium 命令行中添加一个开关。 @@ -312,4 +482,5 @@ Append a switch (with optional `value`) to Chromium's command line. 设置应用的 [dock 菜单][dock-menu]. [dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103 -[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks \ No newline at end of file +[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks +[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx diff --git a/docs-translations/zh-CN/tutorial/application-distribution.md b/docs-translations/zh-CN/tutorial/application-distribution.md index 22a5078c1fa6..dcfe4d240eeb 100644 --- a/docs-translations/zh-CN/tutorial/application-distribution.md +++ b/docs-translations/zh-CN/tutorial/application-distribution.md @@ -55,12 +55,12 @@ electron/resources/ ### Windows 你可以将 `electron.exe` 改成任意你喜欢的名字,然后可以使用像 -[rcedit](https://github.com/atom/rcedit) 或者[ResEdit](http://www.resedit.net) +[rcedit](https://github.com/atom/rcedit) 编辑它的icon和其他信息。 ### OS X -你可以将 `Electron.app` 改成任意你喜欢的名字,然后你也需要修改这些文件中的 +你可以将 `Electron.app` 改成任意你喜欢的名字,然后你也需要修改这些文件中的 `CFBundleDisplayName`, `CFBundleIdentifier` 以及 `CFBundleName` 字段。 这些文件如下: diff --git a/docs-translations/zh-CN/tutorial/quick-start.md b/docs-translations/zh-CN/tutorial/quick-start.md index d54dddbfc93c..5e9c752d1d45 100644 --- a/docs-translations/zh-CN/tutorial/quick-start.md +++ b/docs-translations/zh-CN/tutorial/quick-start.md @@ -14,7 +14,7 @@ Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造 在一般浏览器中,网页通常会在沙盒环境下运行,并且不允许访问原生资源。然而,Electron 用户拥有在网页中调用 io.js 的 APIs 的能力,可以与底层操作系统直接交互。 ## 主进程与渲染进程的区别 -主进程使用 BroswerWindow 实例创建网页。每个 BroswerWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BroswerWindow 实例被销毁后,相应的渲染进程也会被终止。 +主进程使用 BrowserWindow 实例创建网页。每个 BrowserWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。 主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互独立的,并且只关心他们自己的网页。 diff --git a/docs-translations/zh-TW/tutorial/application-distribution.md b/docs-translations/zh-TW/tutorial/application-distribution.md index 60d32f88be00..53561ecfda6e 100644 --- a/docs-translations/zh-TW/tutorial/application-distribution.md +++ b/docs-translations/zh-TW/tutorial/application-distribution.md @@ -50,8 +50,8 @@ electron/resources/ ### Windows -你可以重新命名 `electron.exe` 為任何你喜歡的名稱,然後透過像是 [rcedit](https://github.com/atom/rcedit) 或 -[ResEdit](http://www.resedit.net) 的工具來編輯它的圖示(icon)和其他資訊。 +你可以重新命名 `electron.exe` 為任何你喜歡的名稱,然後透過像是 [rcedit](https://github.com/atom/rcedit) +的工具來編輯它的圖示(icon)和其他資訊。 ### OS X @@ -60,7 +60,7 @@ electron/resources/ * `Electron.app/Contents/Info.plist` * `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist` -你也可以重新命名 helper 應用程式來避免在活動監視器中秀出 `Electron Helper` +你也可以重新命名 helper 應用程式來避免在活動監視器中秀出 `Electron Helper` ,但請確認你有重新命名 helper 應用程式的可執行檔名稱。 重新命名後的應用程式檔案結構可能長得相這樣: diff --git a/docs/api/app.md b/docs/api/app.md index a26defb447a6..adba230b0e2b 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -87,7 +87,7 @@ handle this case (even before the `ready` event is emitted). You should call `event.preventDefault()` if you want to handle this event. -On Windows, you have to parse `process.argv` to get the filepath. +On Windows, you have to parse `process.argv` (in the main process) to get the filepath. ### Event: 'open-url' _OS X_ @@ -244,6 +244,14 @@ This method guarantees that all `beforeunload` and `unload` event handlers are correctly executed. It is possible that a window cancels the quitting by returning `false` in the `beforeunload` event handler. +### `app.hide()` _OS X_ + +Hides all application windows without minimising them. + +### `app.show()` _OS X_ + +Shows application windows after they were hidden. Does not automatically focus them. + ### `app.exit(exitCode)` * `exitCode` Integer diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index edda572e9ac6..7cf684a39539 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -785,7 +785,7 @@ cleared * `description` String - a description that will be provided to Accessibility screen readers -Sets a 16px overlay onto the current taskbar icon, usually used to convey some +Sets a 16 x 16 pixel overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user. ### `win.setHasShadow(hasShadow)` _OS X_ diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index 090fd1a9119d..96936632563e 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -37,9 +37,9 @@ channel. This removes *all* handlers to this ipc channel. -### `ipcMain.once(channel, callback)` +### `ipcRenderer.once(channel, callback)` -Use this in place of `ipcMain.on()` to fire handlers meant to occur only once, +Use this in place of `ipcRenderer.on()` to fire handlers meant to occur only once, as in, they won't be activated after one call of `callback` ## Sending Messages diff --git a/docs/api/menu.md b/docs/api/menu.md index 1de3b4f101ee..49a499a3d4b4 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -296,6 +296,11 @@ no matter what label you set. To change it you have to change your app's name by modifying your app bundle's `Info.plist` file. See [About Information Property List Files][AboutInformationPropertyListFiles] for more information. +## Setting Menu for Specific Browser Window (*Linux* *Windows*) + +The [`setMenu` method][setMenu] of browser windows can set the menu of certain +browser window. + ## Menu Item Position You can make use of `position` and `id` to control how the item will be placed @@ -371,3 +376,5 @@ Menu: ``` [AboutInformationPropertyListFiles]: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html +[setMenu]: +https://github.com/atom/electron/blob/master/docs/api/browser-window.md#winsetmenumenu-linux-windows diff --git a/docs/api/session.md b/docs/api/session.md index fed8c31c7462..cc90a0b542cf 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -60,7 +60,8 @@ The following events are available on instances of `Session`: Emitted when Electron is about to download `item` in `webContents`. -Calling `event.preventDefault()` will cancel the download. +Calling `event.preventDefault()` will cancel the download and `item` will not be +available from next tick of the process. ```javascript session.defaultSession.on('will-download', function(event, item, webContents) { @@ -290,6 +291,35 @@ myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, c }); ``` +#### `ses.setPermissionRequestHandler(handler)` + +* `handler` Function + * `webContents` Object - [WebContents](web-contents.md) requesting the permission. + * `permission` String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen'. + * `callback` Function - Allow or deny the permission. + +Sets the handler which can be used to respond to permission requests for the `session`. +Calling `callback(true)` will allow the permission and `callback(false)` will reject it. + +```javascript +session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) { + if (webContents.getURL() === host) { + if (permission == "notifications") { + callback(false); // denied. + return; + } + } + + callback(true); +}); +``` + +#### `ses.clearHostResolverCache([callback])` + +* `callback` Function (optional) - Called when operation is done. + +Clears the host resolver cache. + #### `ses.webRequest` The `webRequest` API set allows to intercept and modify contents of a request at diff --git a/docs/development/source-code-directory-structure.md b/docs/development/source-code-directory-structure.md index cbca7108526f..146edae822da 100644 --- a/docs/development/source-code-directory-structure.md +++ b/docs/development/source-code-directory-structure.md @@ -58,6 +58,6 @@ Electron * **node_modules** - Third party node modules used for building. * **out** - Temporary output directory of `ninja`. * **dist** - Temporary directory created by `script/create-dist.py` script - when creating an distribution. + when creating a distribution. * **external_binaries** - Downloaded binaries of third-party frameworks which do not support building with `gyp`. diff --git a/docs/tutorial/application-distribution.md b/docs/tutorial/application-distribution.md index e8b944e7f6bd..313c924e881c 100644 --- a/docs/tutorial/application-distribution.md +++ b/docs/tutorial/application-distribution.md @@ -61,8 +61,7 @@ before distributing it to users. ### Windows You can rename `electron.exe` to any name you like, and edit its icon and other -information with tools like [rcedit](https://github.com/atom/rcedit) or -[ResEdit](http://www.resedit.net). +information with tools like [rcedit](https://github.com/atom/rcedit). ### OS X diff --git a/docs/tutorial/supported-platforms.md b/docs/tutorial/supported-platforms.md index 9d1a293d5f5d..a7f736995d20 100644 --- a/docs/tutorial/supported-platforms.md +++ b/docs/tutorial/supported-platforms.md @@ -5,7 +5,7 @@ Following platforms are supported by Electron: ### OS X Only 64bit binaries are provided for OS X, and the minimum OS X version -supported is OS X 10.8. +supported is OS X 10.9. ### Windows diff --git a/filenames.gypi b/filenames.gypi index 748b3b9252cd..a5369570cade 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -144,6 +144,8 @@ 'atom/browser/atom_browser_main_parts_posix.cc', 'atom/browser/atom_javascript_dialog_manager.cc', 'atom/browser/atom_javascript_dialog_manager.h', + 'atom/browser/atom_permission_manager.cc', + 'atom/browser/atom_permission_manager.h', 'atom/browser/atom_quota_permission_context.cc', 'atom/browser/atom_quota_permission_context.h', 'atom/browser/atom_resource_dispatcher_host_delegate.cc', @@ -256,6 +258,8 @@ 'atom/browser/ui/x/window_state_watcher.h', 'atom/browser/ui/x/x_window_utils.cc', 'atom/browser/ui/x/x_window_utils.h', + 'atom/browser/web_contents_permission_helper.cc', + 'atom/browser/web_contents_permission_helper.h', 'atom/browser/web_contents_preferences.cc', 'atom/browser/web_contents_preferences.h', 'atom/browser/web_dialog_helper.cc', diff --git a/package.json b/package.json index 20b97a4c9061..3f0983bc441b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "0.36.6", + "version": "0.36.7", "devDependencies": { "asar": "^0.9.0", "eslint": "^1.10.3", diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index 934020473903..fe27f932cee0 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -144,6 +144,50 @@ describe('session module', function() { }); }); }); + + describe('session will-download event', function() { + var w = null; + + beforeEach(function() { + w = new BrowserWindow({ + show: false, + width: 400, + height: 400 + }); + }); + afterEach(function() { + return w.destroy(); + }); + + it('can cancel default download behavior', function(done) { + const mockFile = new Buffer(1024); + const contentDisposition = 'inline; filename="mockFile.txt"'; + const downloadServer = http.createServer(function(req, res) { + res.writeHead(200, { + 'Content-Length': mockFile.length, + 'Content-Type': 'application/plain', + 'Content-Disposition': contentDisposition + }); + res.end(mockFile); + downloadServer.close(); + }); + + downloadServer.listen(0, '127.0.0.1', function() { + const port = downloadServer.address().port; + const url = "http://127.0.0.1:" + port + '/'; + + ipcRenderer.sendSync('set-download-option', false, true); + w.loadURL(url); + ipcRenderer.once('download-error', function(event, downloadUrl, filename, error) { + assert.equal(downloadUrl, url); + assert.equal(filename, 'mockFile.txt'); + assert.equal(error, 'Object has been destroyed'); + done(); + }); + }); + }); + }); + return describe('DownloadItem', function() { var assertDownload, contentDisposition, downloadFilePath, downloadServer, mockPDF; mockPDF = new Buffer(1024 * 1024 * 5); @@ -173,7 +217,7 @@ describe('session module', function() { return downloadServer.listen(0, '127.0.0.1', function() { var port; port = downloadServer.address().port; - ipcRenderer.sendSync('set-download-option', false); + ipcRenderer.sendSync('set-download-option', false, false); w.loadURL(url + ":" + port); return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); @@ -185,7 +229,7 @@ describe('session module', function() { return downloadServer.listen(0, '127.0.0.1', function() { var port, webview; port = downloadServer.address().port; - ipcRenderer.sendSync('set-download-option', false); + ipcRenderer.sendSync('set-download-option', false, false); webview = new WebView; webview.src = "file://" + fixtures + "/api/blank.html"; webview.addEventListener('did-finish-load', function() { @@ -199,11 +243,11 @@ describe('session module', function() { return document.body.appendChild(webview); }); }); - return it('can cancel download', function(done) { + it('can cancel download', function(done) { return downloadServer.listen(0, '127.0.0.1', function() { var port; port = downloadServer.address().port; - ipcRenderer.sendSync('set-download-option', true); + ipcRenderer.sendSync('set-download-option', true, false); w.loadURL(url + ":" + port + "/"); return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assert.equal(state, 'cancelled'); diff --git a/spec/fixtures/pages/permissions/geolocation.html b/spec/fixtures/pages/permissions/geolocation.html new file mode 100644 index 000000000000..1d1b4fc42451 --- /dev/null +++ b/spec/fixtures/pages/permissions/geolocation.html @@ -0,0 +1,5 @@ + diff --git a/spec/fixtures/pages/permissions/media.html b/spec/fixtures/pages/permissions/media.html new file mode 100644 index 000000000000..0d968a9a66b9 --- /dev/null +++ b/spec/fixtures/pages/permissions/media.html @@ -0,0 +1,7 @@ + diff --git a/spec/fixtures/pages/permissions/midi.html b/spec/fixtures/pages/permissions/midi.html new file mode 100644 index 000000000000..c6bd8c137e36 --- /dev/null +++ b/spec/fixtures/pages/permissions/midi.html @@ -0,0 +1,5 @@ + diff --git a/spec/static/main.js b/spec/static/main.js index 4419a2219b0b..13d2dd6a6e10 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -102,23 +102,35 @@ app.on('ready', function() { // For session's download test, listen 'will-download' event in browser, and // reply the result to renderer for verifying var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); - ipcMain.on('set-download-option', function(event, need_cancel) { - window.webContents.session.once('will-download', - function(e, item, webContents) { - item.setSavePath(downloadFilePath); - item.on('done', function(e, state) { - window.webContents.send('download-done', - state, - item.getURL(), - item.getMimeType(), - item.getReceivedBytes(), - item.getTotalBytes(), - item.getContentDisposition(), - item.getFilename()); - }); - if (need_cancel) - item.cancel(); + ipcMain.on('set-download-option', function(event, need_cancel, prevent_default) { + window.webContents.session.once('will-download', function(e, item, webContents) { + if (prevent_default) { + e.preventDefault(); + const url = item.getURL(); + const filename = item.getFilename(); + setImmediate(function() { + try { + item.getURL(); + } catch(err) { + window.webContents.send('download-error', url, filename, err.message); + } }); + } else { + item.setSavePath(downloadFilePath); + item.on('done', function(e, state) { + window.webContents.send('download-done', + state, + item.getURL(), + item.getMimeType(), + item.getReceivedBytes(), + item.getTotalBytes(), + item.getContentDisposition(), + item.getFilename()); + }); + if (need_cancel) + item.cancel(); + } + }); event.returnValue = "done"; }); }); diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 0eaa59c5fd3c..cac5fb56b444 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -624,7 +624,7 @@ describe(' tag', function() { return document.body.appendChild(webview); }); }); - return xdescribe('did-change-theme-color event', function() { + xdescribe('did-change-theme-color event', function() { return it('emits when theme color changes', function(done) { webview.addEventListener('did-change-theme-color', function() { return done(); @@ -633,4 +633,55 @@ describe(' tag', function() { return document.body.appendChild(webview); }); }); + describe('permission-request event', function() { + function setUpRequestHandler(webview, requested_permission) { + const session = require('electron').remote.session; + var listener = function(webContents, permission, callback) { + if (webContents.getId() === webview.getId() ) { + assert.equal(permission, requested_permission); + callback(false); + } + }; + session.fromPartition(webview.partition).setPermissionRequestHandler(listener); + } + + it ('emits when using navigator.getUserMedia api', function(done) { + webview.addEventListener('ipc-message', function(e) { + assert(e.channel, 'message'); + assert(e.args, ['PermissionDeniedError']); + done(); + }); + webview.src = "file://" + fixtures + "/pages/permissions/media.html"; + webview.partition = "permissionTest"; + webview.setAttribute('nodeintegration', 'on'); + setUpRequestHandler(webview, "media"); + document.body.appendChild(webview); + }); + + it ('emits when using navigator.geolocation api', function(done) { + webview.addEventListener('ipc-message', function(e) { + assert(e.channel, 'message'); + assert(e.args, ['ERROR(1): User denied Geolocation']); + done(); + }); + webview.src = "file://" + fixtures + "/pages/permissions/geolocation.html"; + webview.partition = "permissionTest"; + webview.setAttribute('nodeintegration', 'on'); + setUpRequestHandler(webview, "geolocation"); + document.body.appendChild(webview); + }); + + it ('emits when using navigator.requestMIDIAccess api', function(done) { + webview.addEventListener('ipc-message', function(e) { + assert(e.channel, 'message'); + assert(e.args, ['SecurityError']); + done(); + }); + webview.src = "file://" + fixtures + "/pages/permissions/midi.html"; + webview.partition = "permissionTest"; + webview.setAttribute('nodeintegration', 'on'); + setUpRequestHandler(webview, "midiSysex"); + document.body.appendChild(webview); + }); + }); }); diff --git a/vendor/brightray b/vendor/brightray index ea6011bc9607..2a5cd7178b64 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit ea6011bc9607f321258bf93e510f56f031973230 +Subproject commit 2a5cd7178b641de91ca6eb0bca826fea588f923a diff --git a/vendor/native_mate b/vendor/native_mate index a3dcf8ced663..e719eab878c2 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit a3dcf8ced663e974ac94ad5e50a1d25a43995a9d +Subproject commit e719eab878c264bb03188d0cd6eb9ad6882bc13a