Browse Source

session: allow providing permission to handle external protocols

deepak1556 9 years ago
parent
commit
ca756c3c24

+ 31 - 4
atom/browser/atom_resource_dispatcher_host_delegate.cc

@@ -5,6 +5,7 @@
 #include "atom/browser/atom_resource_dispatcher_host_delegate.h"
 
 #include "atom/browser/login_handler.h"
+#include "atom/browser/web_contents_permission_helper.h"
 #include "atom/common/platform_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/escape.h"
@@ -14,20 +15,46 @@ using content::BrowserThread;
 
 namespace atom {
 
+namespace {
+
+void OnOpenExternal(const GURL& escaped_url,
+                    bool allowed) {
+  if (allowed)
+    platform_util::OpenExternal(escaped_url, true);
+}
+
+void HandleExternalProtocolInUI(
+    const GURL& url,
+    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
+    bool has_user_gesture) {
+  content::WebContents* web_contents = web_contents_getter.Run();
+  if (!web_contents)
+    return;
+
+  GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
+  auto callback = base::Bind(&OnOpenExternal, escaped_url);
+  auto permission_helper =
+      WebContentsPermissionHelper::FromWebContents(web_contents);
+  permission_helper->RequestOpenExternalPermission(callback, has_user_gesture);
+}
+
+}  // namespace
+
 AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
 }
 
 bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
     const GURL& url,
     int child_id,
-    const content::ResourceRequestInfo::WebContentsGetter&,
+    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
     bool is_main_frame,
     ui::PageTransition transition,
     bool has_user_gesture) {
-  GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-      base::Bind(
-          base::IgnoreResult(platform_util::OpenExternal), escaped_url, true));
+                          base::Bind(&HandleExternalProtocolInUI,
+                                     url,
+                                     web_contents_getter,
+                                     has_user_gesture));
   return true;
 }
 

+ 8 - 0
atom/browser/web_contents_permission_helper.cc

@@ -91,4 +91,12 @@ void WebContentsPermissionHelper::RequestPointerLockPermission(
                     user_gesture);
 }
 
+void WebContentsPermissionHelper::RequestOpenExternalPermission(
+    const base::Callback<void(bool)>& callback,
+    bool user_gesture) {
+  RequestPermission((content::PermissionType)(PermissionType::OPEN_EXTERNAL),
+                    callback,
+                    user_gesture);
+}
+
 }  // namespace atom

+ 5 - 1
atom/browser/web_contents_permission_helper.h

@@ -19,7 +19,8 @@ class WebContentsPermissionHelper
 
   enum class PermissionType {
     POINTER_LOCK = static_cast<int>(content::PermissionType::NUM) + 1,
-    FULLSCREEN
+    FULLSCREEN,
+    OPEN_EXTERNAL,
   };
 
   void RequestFullscreenPermission(
@@ -30,6 +31,9 @@ class WebContentsPermissionHelper
   void RequestWebNotificationPermission(
       const base::Callback<void(bool)>& callback);
   void RequestPointerLockPermission(bool user_gesture);
+  void RequestOpenExternalPermission(
+      const base::Callback<void(bool)>& callback,
+      bool user_gesture);
 
  private:
   explicit WebContentsPermissionHelper(content::WebContents* web_contents);

+ 2 - 0
atom/common/native_mate_converters/content_converter.cc

@@ -145,6 +145,8 @@ v8::Local<v8::Value> Converter<content::PermissionType>::ToV8(
     return StringToV8(isolate, "pointerLock");
   else if (val == (content::PermissionType)(PermissionType::FULLSCREEN))
     return StringToV8(isolate, "fullscreen");
+  else if (val == (content::PermissionType)(PermissionType::OPEN_EXTERNAL))
+    return StringToV8(isolate, "openExternal");
 
   return StringToV8(isolate, "unknown");
 }

+ 2 - 1
docs/api/session.md

@@ -295,7 +295,8 @@ myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, c
 
 * `handler` Function
   * `webContents` Object - [WebContents](web-contents.md) requesting the permission.
-  * `permission`  String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen'.
+  * `permission`  String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex',
+    'pointerLock', 'fullscreen', 'openExternal'.
   * `callback`  Function - Allow or deny the permission.
 
 Sets the handler which can be used to respond to permission requests for the `session`.

+ 10 - 1
spec/webview-spec.js

@@ -722,11 +722,13 @@ describe('<webview> tag', function () {
   })
 
   describe('permission-request event', function () {
-    function setUpRequestHandler (webview, requested_permission) {
+    function setUpRequestHandler (webview, requested_permission, completed) {
       var listener = function (webContents, permission, callback) {
         if (webContents.getId() === webview.getId()) {
           assert.equal(permission, requested_permission)
           callback(false)
+          if (completed)
+            completed()
         }
       }
       session.fromPartition(webview.partition).setPermissionRequestHandler(listener)
@@ -770,6 +772,13 @@ describe('<webview> tag', function () {
       setUpRequestHandler(webview, 'midiSysex')
       document.body.appendChild(webview)
     })
+
+    it('emits when accessing external protocol', function (done) {
+      webview.src = 'magnet:test'
+      webview.partition = 'permissionTest'
+      setUpRequestHandler(webview, 'openExternal', done)
+      document.body.appendChild(webview)
+    })
   })
 
   describe('<webview>.getWebContents', function () {