Add support for Asynchronous Clipboard API

Issue #2921 wontfix
Marshall Greenblatt created an issue

The Asynchronous Clipboard API was added in Chrome 66 for the reasons described here. It could be nice for CEF to support this API as a way for client applications to grant or deny clipboard read/write access on a per-origin basis. At the same time, we should provide a way to globally disable the old synchronous API while allowing the new asynchronous API (perhaps via the existing CefSettings.javascript_access_clipboard and CefSettings.javascript_dom_paste options).

Test URL: https://googlechrome.github.io/samples/async-clipboard/

Comments (3)

  1. wanghongliang

    I have fixed in our project on branch 3904, implement content::PermissionControllerDelegate,I put CLIPBOARD_READ/CLIPBOARD_WRITE on the white list by default,these permissions are not authorized by the user. add cef_permission_manager.h/cef_permission_manager.cc.it may be useful

        // cef/BUILD.gn
        "libcef/browser/cef_permission_manager.cc",
        "libcef/browser/cef_permission_manager.h",
    
    // libcef/browser/browser_context.h
    std::unique_ptr<content::PermissionControllerDelegate> permission_manager_;
    // libcef/browser/browser_context.cc
    content::PermissionControllerDelegate*
    CefBrowserContext::GetPermissionControllerDelegate() {
      // return nullptr;
      if (!permission_manager_)
        permission_manager_.reset(new CefPermissionManager());
      return permission_manager_.get();
     }
    
     // "libcef/browser/cef_permission_manager.h"
     // Copyright 2015 The Chromium Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    #ifndef  CEF_LIBCEF_BROWSER_CEF_PERMISSION_MANAGER_H_
    #define  CEF_LIBCEF_BROWSER_CEF_PERMISSION_MANAGER_H_
    
    #include "base/callback_forward.h"
    #include "base/macros.h"
    #include "content/public/browser/permission_controller_delegate.h"
    using content::PermissionType;
    using content::RenderFrameHost;
    class CefPermissionManager : public content::PermissionControllerDelegate {
     public:
      CefPermissionManager();
      ~CefPermissionManager() override;
    
      // PermissionManager implementation.
      int RequestPermission(PermissionType permission,
                            RenderFrameHost* render_frame_host,
                            const GURL& requesting_origin,
                            bool user_gesture,
                            base::OnceCallback<void(blink::mojom::PermissionStatus)>
                                callback) override;
      int RequestPermissions(
          const std::vector<PermissionType>& permission,
          RenderFrameHost* render_frame_host,
          const GURL& requesting_origin,
          bool user_gesture,
          base::OnceCallback<
              void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
          override;
      void ResetPermission(PermissionType permission,
                           const GURL& requesting_origin,
                           const GURL& embedding_origin) override;
      blink::mojom::PermissionStatus GetPermissionStatus(
          PermissionType permission,
          const GURL& requesting_origin,
          const GURL& embedding_origin) override;
      blink::mojom::PermissionStatus GetPermissionStatusForFrame(
          content::PermissionType permission,
          content::RenderFrameHost* render_frame_host,
          const GURL& requesting_origin) override;
      int SubscribePermissionStatusChange(
          PermissionType permission,
          RenderFrameHost* render_frame_host,
          const GURL& requesting_origin,
          base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
          override;
      void UnsubscribePermissionStatusChange(int subscription_id) override;
    
     private:
      DISALLOW_COPY_AND_ASSIGN(CefPermissionManager);
    };
    
    #endif //  CEF_LIBCEF_BROWSER_CEF_PERMISSION_MANAGER_H_
    
    
    
    // "libcef/browser/cef_permission_manager.cc"
    // Copyright 2015 The Chromium Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    #include "libcef/browser/cef_permission_manager.h"
    
    #include "base/callback.h"
    #include "base/command_line.h"
    #include "content/public/browser/permission_controller.h"
    #include "content/public/browser/permission_type.h"
    #include "content/public/browser/web_contents.h"
    #include "content/public/common/content_switches.h"
    #include "content/shell/common/shell_switches.h"
    #include "media/base/media_switches.h"
    
    namespace {
    
    bool IsWhitelistedPermissionType(PermissionType permission) {
      switch (permission) {
        case PermissionType::GEOLOCATION:
        case PermissionType::MIDI:
        case PermissionType::SENSORS:
        case PermissionType::ACCESSIBILITY_EVENTS:
        case PermissionType::PAYMENT_HANDLER:
        case PermissionType::WAKE_LOCK_SCREEN:
    
        // Background Sync and Background Fetch browser tests require
        // permission to be granted by default.
        case PermissionType::BACKGROUND_SYNC:
        case PermissionType::BACKGROUND_FETCH:
        case PermissionType::PERIODIC_BACKGROUND_SYNC:
    
        case PermissionType::IDLE_DETECTION:
        case PermissionType::CLIPBOARD_READ:
        case PermissionType::CLIPBOARD_WRITE:
          return true;
        case PermissionType::MIDI_SYSEX:
        case PermissionType::NOTIFICATIONS:
        case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
        case PermissionType::DURABLE_STORAGE:
        case PermissionType::AUDIO_CAPTURE:
        case PermissionType::VIDEO_CAPTURE:
        case PermissionType::FLASH:
        case PermissionType::NUM:
        case PermissionType::WAKE_LOCK_SYSTEM:
          return false;
      }
    
      NOTREACHED();
      return false;
    }
    
    }  // namespace
    
    CefPermissionManager::CefPermissionManager() = default;
    
    CefPermissionManager::~CefPermissionManager() {
    }
    
    int CefPermissionManager::RequestPermission(
        PermissionType permission,
        RenderFrameHost* render_frame_host,
        const GURL& requesting_origin,
        bool user_gesture,
        base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {
      std::move(callback).Run(IsWhitelistedPermissionType(permission)
                                  ? blink::mojom::PermissionStatus::GRANTED
                                  : blink::mojom::PermissionStatus::DENIED);
      return content::PermissionController::kNoPendingOperation;
    }
    
    int CefPermissionManager::RequestPermissions(
        const std::vector<PermissionType>& permissions,
        content::RenderFrameHost* render_frame_host,
        const GURL& requesting_origin,
        bool user_gesture,
        base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
            callback) {
      std::vector<blink::mojom::PermissionStatus> result;
      for (const auto& permission : permissions) {
        result.push_back(IsWhitelistedPermissionType(permission)
                             ? blink::mojom::PermissionStatus::GRANTED
                             : blink::mojom::PermissionStatus::DENIED);
      }
      std::move(callback).Run(result);
      return content::PermissionController::kNoPendingOperation;
    }
    
    void CefPermissionManager::ResetPermission(
        PermissionType permission,
        const GURL& requesting_origin,
        const GURL& embedding_origin) {
    }
    
    blink::mojom::PermissionStatus CefPermissionManager::GetPermissionStatus(
        PermissionType permission,
        const GURL& requesting_origin,
        const GURL& embedding_origin) {
      return IsWhitelistedPermissionType(permission)
                 ? blink::mojom::PermissionStatus::GRANTED
                 : blink::mojom::PermissionStatus::DENIED;
    }
    
    blink::mojom::PermissionStatus
    CefPermissionManager::GetPermissionStatusForFrame(
        PermissionType permission,
        content::RenderFrameHost* render_frame_host,
        const GURL& requesting_origin) {
      return GetPermissionStatus(
          permission, requesting_origin,
          content::WebContents::FromRenderFrameHost(render_frame_host)
              ->GetLastCommittedURL()
              .GetOrigin());
    }
    
    int CefPermissionManager::SubscribePermissionStatusChange(
        PermissionType permission,
        RenderFrameHost* render_frame_host,
        const GURL& requesting_origin,
        base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) {
      return content::PermissionController::kNoPendingOperation;
    }
    
    void CefPermissionManager::UnsubscribePermissionStatusChange(
        int subscription_id) {
    }
    

  2. Jacob Hoover

    @wanghongliang I attempted to use this suggested fix rebased on to 4389. While I got it to compile, I don’t see any change in behavior. Has something changed between 3904 and 4389 that would require additional changes to get this to work?

    Possibly related to chromiumembedded / cef / commit / 48fc0bd2206d — Bitbucket , trying to remove the AlloyBrowserContext::GetPermissionControllerDelegate

    Edit: It appears to work if I change libcef/browser/alloy/alloy_browser_context.cc:

    content::PermissionControllerDelegate*
    AlloyBrowserContext::GetPermissionControllerDelegate() {
    // return nullptr;
    return CefBrowserContext::GetPermissionControllerDelegate();
    }

  3. Log in to comment