feat: add session.setPermissionCheckHandler (#13925)
* feat: add session.setPermissionCheckHandler to handle syncornous permission checks vs requests * spec: add tests for session.setPermissionCheckHandler * docs: add docs for session.setPermissionCheckHandler * feat: add mediaType to media permission checks * chore: cleanup check impl
This commit is contained in:
		
					parent
					
						
							
								afdb6c5f90
							
						
					
				
			
			
				commit
				
					
						68da311ed1
					
				
			
		
					 10 changed files with 142 additions and 1 deletions
				
			
		| 
						 | 
					@ -627,6 +627,18 @@ void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
 | 
				
			||||||
  permission_manager->SetPermissionRequestHandler(handler);
 | 
					  permission_manager->SetPermissionRequestHandler(handler);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
 | 
				
			||||||
 | 
					                                        mate::Arguments* args) {
 | 
				
			||||||
 | 
					  AtomPermissionManager::CheckHandler handler;
 | 
				
			||||||
 | 
					  if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) {
 | 
				
			||||||
 | 
					    args->ThrowError("Must pass null or function");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  auto* permission_manager = static_cast<AtomPermissionManager*>(
 | 
				
			||||||
 | 
					      browser_context()->GetPermissionManager());
 | 
				
			||||||
 | 
					  permission_manager->SetPermissionCheckHandler(handler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Session::ClearHostResolverCache(mate::Arguments* args) {
 | 
					void Session::ClearHostResolverCache(mate::Arguments* args) {
 | 
				
			||||||
  base::Closure callback;
 | 
					  base::Closure callback;
 | 
				
			||||||
  args->GetNext(&callback);
 | 
					  args->GetNext(&callback);
 | 
				
			||||||
| 
						 | 
					@ -814,6 +826,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
 | 
				
			||||||
      .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
 | 
					      .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
 | 
				
			||||||
      .SetMethod("setPermissionRequestHandler",
 | 
					      .SetMethod("setPermissionRequestHandler",
 | 
				
			||||||
                 &Session::SetPermissionRequestHandler)
 | 
					                 &Session::SetPermissionRequestHandler)
 | 
				
			||||||
 | 
					      .SetMethod("setPermissionCheckHandler",
 | 
				
			||||||
 | 
					                 &Session::SetPermissionCheckHandler)
 | 
				
			||||||
      .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
 | 
					      .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
 | 
				
			||||||
      .SetMethod("clearAuthCache", &Session::ClearAuthCache)
 | 
					      .SetMethod("clearAuthCache", &Session::ClearAuthCache)
 | 
				
			||||||
      .SetMethod("allowNTLMCredentialsForDomains",
 | 
					      .SetMethod("allowNTLMCredentialsForDomains",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,8 @@ class Session : public mate::TrackableObject<Session>,
 | 
				
			||||||
  void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
 | 
					  void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
 | 
				
			||||||
  void SetPermissionRequestHandler(v8::Local<v8::Value> val,
 | 
					  void SetPermissionRequestHandler(v8::Local<v8::Value> val,
 | 
				
			||||||
                                   mate::Arguments* args);
 | 
					                                   mate::Arguments* args);
 | 
				
			||||||
 | 
					  void SetPermissionCheckHandler(v8::Local<v8::Value> val,
 | 
				
			||||||
 | 
					                                 mate::Arguments* args);
 | 
				
			||||||
  void ClearHostResolverCache(mate::Arguments* args);
 | 
					  void ClearHostResolverCache(mate::Arguments* args);
 | 
				
			||||||
  void ClearAuthCache(mate::Arguments* args);
 | 
					  void ClearAuthCache(mate::Arguments* args);
 | 
				
			||||||
  void AllowNTLMCredentialsForDomains(const std::string& domains);
 | 
					  void AllowNTLMCredentialsForDomains(const std::string& domains);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -718,7 +718,9 @@ void WebContents::FindReply(content::WebContents* web_contents,
 | 
				
			||||||
bool WebContents::CheckMediaAccessPermission(content::WebContents* web_contents,
 | 
					bool WebContents::CheckMediaAccessPermission(content::WebContents* web_contents,
 | 
				
			||||||
                                             const GURL& security_origin,
 | 
					                                             const GURL& security_origin,
 | 
				
			||||||
                                             content::MediaStreamType type) {
 | 
					                                             content::MediaStreamType type) {
 | 
				
			||||||
  return true;
 | 
					  auto* permission_helper =
 | 
				
			||||||
 | 
					      WebContentsPermissionHelper::FromWebContents(web_contents);
 | 
				
			||||||
 | 
					  return permission_helper->CheckMediaAccessPermission(security_origin, type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WebContents::RequestMediaAccessPermission(
 | 
					void WebContents::RequestMediaAccessPermission(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,6 +100,11 @@ void AtomPermissionManager::SetPermissionRequestHandler(
 | 
				
			||||||
  request_handler_ = handler;
 | 
					  request_handler_ = handler;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AtomPermissionManager::SetPermissionCheckHandler(
 | 
				
			||||||
 | 
					    const CheckHandler& handler) {
 | 
				
			||||||
 | 
					  check_handler_ = handler;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int AtomPermissionManager::RequestPermission(
 | 
					int AtomPermissionManager::RequestPermission(
 | 
				
			||||||
    content::PermissionType permission,
 | 
					    content::PermissionType permission,
 | 
				
			||||||
    content::RenderFrameHost* render_frame_host,
 | 
					    content::RenderFrameHost* render_frame_host,
 | 
				
			||||||
| 
						 | 
					@ -223,4 +228,18 @@ int AtomPermissionManager::SubscribePermissionStatusChange(
 | 
				
			||||||
void AtomPermissionManager::UnsubscribePermissionStatusChange(
 | 
					void AtomPermissionManager::UnsubscribePermissionStatusChange(
 | 
				
			||||||
    int subscription_id) {}
 | 
					    int subscription_id) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AtomPermissionManager::CheckPermissionWithDetails(
 | 
				
			||||||
 | 
					    content::PermissionType permission,
 | 
				
			||||||
 | 
					    content::RenderFrameHost* render_frame_host,
 | 
				
			||||||
 | 
					    const GURL& requesting_origin,
 | 
				
			||||||
 | 
					    const base::DictionaryValue* details) const {
 | 
				
			||||||
 | 
					  if (check_handler_.is_null()) {
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  auto* web_contents =
 | 
				
			||||||
 | 
					      content::WebContents::FromRenderFrameHost(render_frame_host);
 | 
				
			||||||
 | 
					  return check_handler_.Run(web_contents, permission, requesting_origin,
 | 
				
			||||||
 | 
					                            *details);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace atom
 | 
					}  // namespace atom
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,14 @@ class AtomPermissionManager : public content::PermissionManager {
 | 
				
			||||||
                                             content::PermissionType,
 | 
					                                             content::PermissionType,
 | 
				
			||||||
                                             const StatusCallback&,
 | 
					                                             const StatusCallback&,
 | 
				
			||||||
                                             const base::DictionaryValue&)>;
 | 
					                                             const base::DictionaryValue&)>;
 | 
				
			||||||
 | 
					  using CheckHandler = base::Callback<bool(content::WebContents*,
 | 
				
			||||||
 | 
					                                           content::PermissionType,
 | 
				
			||||||
 | 
					                                           const GURL& requesting_origin,
 | 
				
			||||||
 | 
					                                           const base::DictionaryValue&)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Handler to dispatch permission requests in JS.
 | 
					  // Handler to dispatch permission requests in JS.
 | 
				
			||||||
  void SetPermissionRequestHandler(const RequestHandler& handler);
 | 
					  void SetPermissionRequestHandler(const RequestHandler& handler);
 | 
				
			||||||
 | 
					  void SetPermissionCheckHandler(const CheckHandler& handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // content::PermissionManager:
 | 
					  // content::PermissionManager:
 | 
				
			||||||
  int RequestPermission(
 | 
					  int RequestPermission(
 | 
				
			||||||
| 
						 | 
					@ -67,6 +72,11 @@ class AtomPermissionManager : public content::PermissionManager {
 | 
				
			||||||
      const base::Callback<
 | 
					      const base::Callback<
 | 
				
			||||||
          void(const std::vector<blink::mojom::PermissionStatus>&)>& callback);
 | 
					          void(const std::vector<blink::mojom::PermissionStatus>&)>& callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool CheckPermissionWithDetails(content::PermissionType permission,
 | 
				
			||||||
 | 
					                                  content::RenderFrameHost* render_frame_host,
 | 
				
			||||||
 | 
					                                  const GURL& requesting_origin,
 | 
				
			||||||
 | 
					                                  const base::DictionaryValue* details) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  void OnPermissionResponse(int request_id,
 | 
					  void OnPermissionResponse(int request_id,
 | 
				
			||||||
                            int permission_id,
 | 
					                            int permission_id,
 | 
				
			||||||
| 
						 | 
					@ -93,6 +103,7 @@ class AtomPermissionManager : public content::PermissionManager {
 | 
				
			||||||
  using PendingRequestsMap = base::IDMap<std::unique_ptr<PendingRequest>>;
 | 
					  using PendingRequestsMap = base::IDMap<std::unique_ptr<PendingRequest>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  RequestHandler request_handler_;
 | 
					  RequestHandler request_handler_;
 | 
				
			||||||
 | 
					  CheckHandler check_handler_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PendingRequestsMap pending_requests_;
 | 
					  PendingRequestsMap pending_requests_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,21 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPermissionHelper);
 | 
					DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPermissionHelper);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string MediaStreamTypeToString(content::MediaStreamType type) {
 | 
				
			||||||
 | 
					  switch (type) {
 | 
				
			||||||
 | 
					    case content::MediaStreamType::MEDIA_DEVICE_AUDIO_CAPTURE:
 | 
				
			||||||
 | 
					      return "audio";
 | 
				
			||||||
 | 
					    case content::MediaStreamType::MEDIA_DEVICE_VIDEO_CAPTURE:
 | 
				
			||||||
 | 
					      return "video";
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return "unknown";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace atom {
 | 
					namespace atom {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
| 
						 | 
					@ -63,6 +78,17 @@ void WebContentsPermissionHelper::RequestPermission(
 | 
				
			||||||
      base::Bind(&OnPermissionResponse, callback));
 | 
					      base::Bind(&OnPermissionResponse, callback));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool WebContentsPermissionHelper::CheckPermission(
 | 
				
			||||||
 | 
					    content::PermissionType permission,
 | 
				
			||||||
 | 
					    const base::DictionaryValue* details) const {
 | 
				
			||||||
 | 
					  auto* rfh = web_contents_->GetMainFrame();
 | 
				
			||||||
 | 
					  auto* permission_manager = static_cast<AtomPermissionManager*>(
 | 
				
			||||||
 | 
					      web_contents_->GetBrowserContext()->GetPermissionManager());
 | 
				
			||||||
 | 
					  auto origin = web_contents_->GetLastCommittedURL();
 | 
				
			||||||
 | 
					  return permission_manager->CheckPermissionWithDetails(permission, rfh, origin,
 | 
				
			||||||
 | 
					                                                        details);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WebContentsPermissionHelper::RequestFullscreenPermission(
 | 
					void WebContentsPermissionHelper::RequestFullscreenPermission(
 | 
				
			||||||
    const base::Callback<void(bool)>& callback) {
 | 
					    const base::Callback<void(bool)>& callback) {
 | 
				
			||||||
  RequestPermission(
 | 
					  RequestPermission(
 | 
				
			||||||
| 
						 | 
					@ -102,4 +128,15 @@ void WebContentsPermissionHelper::RequestOpenExternalPermission(
 | 
				
			||||||
      callback, user_gesture, &details);
 | 
					      callback, user_gesture, &details);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool WebContentsPermissionHelper::CheckMediaAccessPermission(
 | 
				
			||||||
 | 
					    const GURL& security_origin,
 | 
				
			||||||
 | 
					    content::MediaStreamType type) const {
 | 
				
			||||||
 | 
					  base::DictionaryValue details;
 | 
				
			||||||
 | 
					  details.SetString("securityOrigin", security_origin.spec());
 | 
				
			||||||
 | 
					  details.SetString("mediaType", MediaStreamTypeToString(type));
 | 
				
			||||||
 | 
					  // The permission type doesn't matter here, AUDIO_CAPTURE/VIDEO_CAPTURE
 | 
				
			||||||
 | 
					  // are presented as same type in content_converter.h.
 | 
				
			||||||
 | 
					  return CheckPermission(content::PermissionType::AUDIO_CAPTURE, &details);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace atom
 | 
					}  // namespace atom
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ class WebContentsPermissionHelper
 | 
				
			||||||
    OPEN_EXTERNAL,
 | 
					    OPEN_EXTERNAL,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Asynchronous Requests
 | 
				
			||||||
  void RequestFullscreenPermission(const base::Callback<void(bool)>& callback);
 | 
					  void RequestFullscreenPermission(const base::Callback<void(bool)>& callback);
 | 
				
			||||||
  void RequestMediaAccessPermission(
 | 
					  void RequestMediaAccessPermission(
 | 
				
			||||||
      const content::MediaStreamRequest& request,
 | 
					      const content::MediaStreamRequest& request,
 | 
				
			||||||
| 
						 | 
					@ -34,6 +35,10 @@ class WebContentsPermissionHelper
 | 
				
			||||||
                                     bool user_gesture,
 | 
					                                     bool user_gesture,
 | 
				
			||||||
                                     const GURL& url);
 | 
					                                     const GURL& url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Synchronous Checks
 | 
				
			||||||
 | 
					  bool CheckMediaAccessPermission(const GURL& security_origin,
 | 
				
			||||||
 | 
					                                  content::MediaStreamType type) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  explicit WebContentsPermissionHelper(content::WebContents* web_contents);
 | 
					  explicit WebContentsPermissionHelper(content::WebContents* web_contents);
 | 
				
			||||||
  friend class content::WebContentsUserData<WebContentsPermissionHelper>;
 | 
					  friend class content::WebContentsUserData<WebContentsPermissionHelper>;
 | 
				
			||||||
| 
						 | 
					@ -43,6 +48,9 @@ class WebContentsPermissionHelper
 | 
				
			||||||
                         bool user_gesture = false,
 | 
					                         bool user_gesture = false,
 | 
				
			||||||
                         const base::DictionaryValue* details = nullptr);
 | 
					                         const base::DictionaryValue* details = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool CheckPermission(content::PermissionType permission,
 | 
				
			||||||
 | 
					                       const base::DictionaryValue* details) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  content::WebContents* web_contents_;
 | 
					  content::WebContents* web_contents_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DISALLOW_COPY_AND_ASSIGN(WebContentsPermissionHelper);
 | 
					  DISALLOW_COPY_AND_ASSIGN(WebContentsPermissionHelper);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,6 +311,32 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### `ses.setPermissionCheckHandler(handler)`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `handler` Function<Boolean> | null
 | 
				
			||||||
 | 
					  * `webContents` [WebContents](web-contents.md) - WebContents checking the permission.
 | 
				
			||||||
 | 
					  * `permission` String - Enum of 'media'.
 | 
				
			||||||
 | 
					  * `requestingOrigin` String - The origin URL of the permission check
 | 
				
			||||||
 | 
					  * `details` Object - Some properties are only available on certain permission types.
 | 
				
			||||||
 | 
					    * `securityOrigin` String - The security orign of the `media` check.
 | 
				
			||||||
 | 
					    * `mediaType` String - The type of media access being requested, can be `video`,
 | 
				
			||||||
 | 
					      `audio` or `unknown`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sets the handler which can be used to respond to permission checks for the `session`.
 | 
				
			||||||
 | 
					Returning `true` will allow the permission and `false` will reject it.
 | 
				
			||||||
 | 
					To clear the handler, call `setPermissionCheckHandler(null)`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```javascript
 | 
				
			||||||
 | 
					const {session} = require('electron')
 | 
				
			||||||
 | 
					session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission) => {
 | 
				
			||||||
 | 
					  if (webContents.getURL() === 'some-host' && permission === 'notifications') {
 | 
				
			||||||
 | 
					    return false // denied
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return true
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `ses.clearHostResolverCache([callback])`
 | 
					#### `ses.clearHostResolverCache([callback])`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `callback` Function (optional) - Called when operation is done.
 | 
					* `callback` Function (optional) - Called when operation is done.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,10 @@ describe('chromium feature', () => {
 | 
				
			||||||
  describe('navigator.mediaDevices', () => {
 | 
					  describe('navigator.mediaDevices', () => {
 | 
				
			||||||
    if (isCI) return
 | 
					    if (isCI) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    afterEach(() => {
 | 
				
			||||||
 | 
					      remote.getGlobal('permissionChecks').allow()
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('can return labels of enumerated devices', (done) => {
 | 
					    it('can return labels of enumerated devices', (done) => {
 | 
				
			||||||
      navigator.mediaDevices.enumerateDevices().then((devices) => {
 | 
					      navigator.mediaDevices.enumerateDevices().then((devices) => {
 | 
				
			||||||
        const labels = devices.map((device) => device.label)
 | 
					        const labels = devices.map((device) => device.label)
 | 
				
			||||||
| 
						 | 
					@ -118,6 +122,19 @@ describe('chromium feature', () => {
 | 
				
			||||||
      }).catch(done)
 | 
					      }).catch(done)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('does not return labels of enumerated devices when permission denied', (done) => {
 | 
				
			||||||
 | 
					      remote.getGlobal('permissionChecks').reject()
 | 
				
			||||||
 | 
					      navigator.mediaDevices.enumerateDevices().then((devices) => {
 | 
				
			||||||
 | 
					        const labels = devices.map((device) => device.label)
 | 
				
			||||||
 | 
					        const labelFound = labels.some((label) => !!label)
 | 
				
			||||||
 | 
					        if (labelFound) {
 | 
				
			||||||
 | 
					          done(new Error(`Device labels were found: ${JSON.stringify(labels)}`))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          done()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }).catch(done)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('can return new device id when cookie storage is cleared', (done) => {
 | 
					    it('can return new device id when cookie storage is cleared', (done) => {
 | 
				
			||||||
      const options = {
 | 
					      const options = {
 | 
				
			||||||
        origin: null,
 | 
					        origin: null,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,11 @@ ipcMain.on('echo', function (event, msg) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
global.setTimeoutPromisified = util.promisify(setTimeout)
 | 
					global.setTimeoutPromisified = util.promisify(setTimeout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					global.permissionChecks = {
 | 
				
			||||||
 | 
					  allow: () => electron.session.defaultSession.setPermissionCheckHandler(null),
 | 
				
			||||||
 | 
					  reject: () => electron.session.defaultSession.setPermissionCheckHandler(() => false)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const coverage = new Coverage({
 | 
					const coverage = new Coverage({
 | 
				
			||||||
  outputPath: path.join(__dirname, '..', '..', 'out', 'coverage')
 | 
					  outputPath: path.join(__dirname, '..', '..', 'out', 'coverage')
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue