Changeset 269918 in webkit


Ignore:
Timestamp:
Nov 17, 2020 1:00:46 PM (3 years ago)
Author:
sihui_liu@apple.com
Message:

Add a default action for SpeechRecognition permission request
https://bugs.webkit.org/show_bug.cgi?id=219021

Reviewed by Youenn Fablet.

Source/WebCore:

Manually tested in Minibrowser.

  • en.lproj/Localizable.strings:

Source/WebKit:

When there is no delegate or selector for deciding user permission on speech recognition, force an alert and let
user decide. This is currently what we do for UserMedia permission request, and it makes testing easier.

  • SourcesCocoa.txt:
  • UIProcess/API/APIUIClient.h:

(API::UIClient::decidePolicyForSpeechRecognitionPermissionRequest):

  • UIProcess/Cocoa/MediaPermissionUtilities.mm:

(WebKit::visibleDomain):
(WebKit::alertMessageText):
(WebKit::allowButtonText):
(WebKit::doNotAllowButtonText):
(WebKit::alertForPermission):

  • UIProcess/Cocoa/UIDelegate.mm:

(WebKit::UIDelegate::UIClient::decidePolicyForSpeechRecognitionPermissionRequest):

  • UIProcess/Cocoa/UserMediaPermissionRequestProxy.mm: Removed. Moved alert code to MediaPermissionUtilities so

it can be shared between UserMedia and SpeechRecognition.

  • UIProcess/MediaPermissionUtilities.h:
  • UIProcess/SpeechRecognitionPermissionManager.cpp:

(WebKit::SpeechRecognitionPermissionManager::decideByDefaultAction):

  • UIProcess/SpeechRecognitionPermissionManager.h:
  • UIProcess/UserMediaPermissionRequestProxy.cpp:

(WebKit::UserMediaPermissionRequestProxy::doDefaultAction):

  • UIProcess/UserMediaPermissionRequestProxy.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::requestSpeechRecognitionPermissionByDefaultAction):

  • UIProcess/WebPageProxy.h:
  • WebKit.xcodeproj/project.pbxproj:
Location:
trunk/Source
Files:
1 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r269916 r269918  
     12020-11-17  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Add a default action for SpeechRecognition permission request
     4        https://bugs.webkit.org/show_bug.cgi?id=219021
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Manually tested in Minibrowser.
     9
     10        * en.lproj/Localizable.strings:
     11
    1122020-11-17  Antti Koivisto  <antti@apple.com>
    213
  • trunk/Source/WebCore/en.lproj/Localizable.strings

    r268605 r269918  
    143143"Don’t Allow (usermedia)" = "Don’t Allow";
    144144
     145/* Message for speech recognition prompt */
     146"Allow “%@” to capture your audio and use it for speech recognition?" = "Allow “%@” to capture your audio and use it for speech recognition?";
     147
     148/* Allow button title in speech recognition prompt */
     149"Allow (speechrecognition)" = "Allow";
     150
     151/* Disallow button title in speech recognition prompt */
     152"Don’t Allow (speechrecognition)" = "Don’t Allow";
     153
    145154/* WKErrorUnknown description */
    146155"An unknown error occurred" = "An unknown error occurred";
  • trunk/Source/WebKit/ChangeLog

    r269917 r269918  
     12020-11-17  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Add a default action for SpeechRecognition permission request
     4        https://bugs.webkit.org/show_bug.cgi?id=219021
     5
     6        Reviewed by Youenn Fablet.
     7
     8        When there is no delegate or selector for deciding user permission on speech recognition, force an alert and let
     9        user decide. This is currently what we do for UserMedia permission request, and it makes testing easier.
     10
     11        * SourcesCocoa.txt:
     12        * UIProcess/API/APIUIClient.h:
     13        (API::UIClient::decidePolicyForSpeechRecognitionPermissionRequest):
     14        * UIProcess/Cocoa/MediaPermissionUtilities.mm:
     15        (WebKit::visibleDomain):
     16        (WebKit::alertMessageText):
     17        (WebKit::allowButtonText):
     18        (WebKit::doNotAllowButtonText):
     19        (WebKit::alertForPermission):
     20        * UIProcess/Cocoa/UIDelegate.mm:
     21        (WebKit::UIDelegate::UIClient::decidePolicyForSpeechRecognitionPermissionRequest):
     22        * UIProcess/Cocoa/UserMediaPermissionRequestProxy.mm: Removed. Moved alert code to MediaPermissionUtilities so
     23        it can be shared between UserMedia and SpeechRecognition.
     24        * UIProcess/MediaPermissionUtilities.h:
     25        * UIProcess/SpeechRecognitionPermissionManager.cpp:
     26        (WebKit::SpeechRecognitionPermissionManager::decideByDefaultAction):
     27        * UIProcess/SpeechRecognitionPermissionManager.h:
     28        * UIProcess/UserMediaPermissionRequestProxy.cpp:
     29        (WebKit::UserMediaPermissionRequestProxy::doDefaultAction):
     30        * UIProcess/UserMediaPermissionRequestProxy.h:
     31        * UIProcess/WebPageProxy.cpp:
     32        (WebKit::WebPageProxy::requestSpeechRecognitionPermissionByDefaultAction):
     33        * UIProcess/WebPageProxy.h:
     34        * WebKit.xcodeproj/project.pbxproj:
     35
    1362020-11-17  Saagar Jha  <saagar@saagarjha.com>
    237
  • trunk/Source/WebKit/SourcesCocoa.txt

    r269810 r269918  
    388388UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
    389389UIProcess/Cocoa/UserMediaPermissionRequestManagerProxy.mm
    390 UIProcess/Cocoa/UserMediaPermissionRequestProxy.mm
    391390UIProcess/Cocoa/VideoFullscreenManagerProxy.mm
    392391UIProcess/Cocoa/WebPageProxyCocoa.mm
  • trunk/Source/WebKit/UIProcess/API/APIUIClient.h

    r269810 r269918  
    203203    }
    204204
    205     virtual void decidePolicyForSpeechRecognitionPermissionRequest(WebKit::WebPageProxy&, API::SecurityOrigin&, CompletionHandler<void(bool)>&& completionHandler) { completionHandler(false); }
     205    virtual void decidePolicyForSpeechRecognitionPermissionRequest(WebKit::WebPageProxy& page, API::SecurityOrigin& origin, CompletionHandler<void(bool)>&& completionHandler) { page.requestSpeechRecognitionPermissionByDefaultAction(origin.securityOrigin(), WTFMove(completionHandler)); }
    206206};
    207207
  • trunk/Source/WebKit/UIProcess/Cocoa/MediaPermissionUtilities.mm

    r269810 r269918  
    2929#import "SandboxUtilities.h"
    3030#import "TCCSPI.h"
     31#import "WKWebViewInternal.h"
     32#import "WebPageProxy.h"
     33#import <WebCore/LocalizedStrings.h>
     34#import <WebCore/SecurityOrigin.h>
    3135#import <mutex>
    3236#import <wtf/BlockPtr.h>
    3337#import <wtf/SoftLinking.h>
     38#import <wtf/URLHelpers.h>
    3439#import <wtf/spi/darwin/SandboxSPI.h>
    3540
     
    112117}
    113118
     119static NSString* visibleDomain(const String& host)
     120{
     121    auto domain = WTF::URLHelpers::userVisibleURL(host.utf8());
     122    return startsWithLettersIgnoringASCIICase(domain, "www.") ? domain.substring(4) : domain;
     123}
     124
     125static NSString *alertMessageText(MediaPermissionReason reason, OptionSet<MediaPermissionType> types, const WebCore::SecurityOrigin& origin)
     126{
     127    if (origin.protocol() != "http" && origin.protocol() != "https")
     128        return nil;
     129
     130    switch (reason) {
     131    case MediaPermissionReason::UserMedia:
     132        if (types.contains(MediaPermissionType::Audio) && types.contains(MediaPermissionType::Video))
     133            return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to use your camera and microphone?", @"Message for user media prompt"), visibleDomain(origin.host())];
     134        if (types.contains(MediaPermissionType::Audio))
     135            return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to use your microphone?", @"Message for user microphone access prompt"), visibleDomain(origin.host())];
     136        if (types.contains(MediaPermissionType::Audio))
     137            return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to use your camera?", @"Message for user camera access prompt"), visibleDomain(origin.host())];
     138        return nil;
     139    case MediaPermissionReason::SpeechRecognition:
     140        return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to capture your audio and use it for speech recognition?", @"Message for spechrecognition prompt"), visibleDomain(origin.host())];
     141    }
     142}
     143
     144static NSString *allowButtonText(MediaPermissionReason reason)
     145{
     146    switch (reason) {
     147    case MediaPermissionReason::UserMedia:
     148        return WEB_UI_STRING_KEY(@"Allow", "Allow (usermedia)", @"Allow button title in user media prompt");
     149    case MediaPermissionReason::SpeechRecognition:
     150        return WEB_UI_STRING_KEY(@"Allow", "Allow (speechrecognition)", @"Allow button title in speech recognition prompt");
     151    }
     152}
     153
     154static NSString *doNotAllowButtonText(MediaPermissionReason reason)
     155{
     156    switch (reason) {
     157    case MediaPermissionReason::UserMedia:
     158        return WEB_UI_STRING_KEY(@"Don’t Allow", "Don’t Allow (usermedia)", @"Disallow button title in user media prompt");
     159    case MediaPermissionReason::SpeechRecognition:
     160        return WEB_UI_STRING_KEY(@"Don’t Allow", "Don’t Allow (speechrecognition)", @"Disallow button title in speech recognition prompt");
     161    }
     162}
     163
     164void alertForPermission(WebPageProxy& page, MediaPermissionReason reason, OptionSet<MediaPermissionType> types, const WebCore::SecurityOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
     165{
     166    auto *webView = fromWebPageProxy(page);
     167    if (!webView) {
     168        completionHandler(false);
     169        return;
     170    }
     171   
     172    auto *alertTitle = alertMessageText(reason, types, origin);
     173    if (!alertTitle) {
     174        completionHandler(false);
     175        return;
     176    }
     177
     178    auto *allowButtonString = allowButtonText(reason);
     179    auto *doNotAllowButtonString = doNotAllowButtonText(reason);
     180    auto completionBlock = makeBlockPtr(WTFMove(completionHandler));
     181
     182#if PLATFORM(MAC)
     183    auto alert = adoptNS([NSAlert new]);
     184    [alert setMessageText:alertTitle];
     185    [alert addButtonWithTitle:doNotAllowButtonString];
     186    [alert addButtonWithTitle:allowButtonString];
     187    [alert beginSheetModalForWindow:webView.window completionHandler:[completionBlock](NSModalResponse returnCode) {
     188        auto shouldAllow = returnCode == NSAlertSecondButtonReturn;
     189        completionBlock(shouldAllow);
     190    }];
     191#else
     192    UIAlertController* alert = [UIAlertController alertControllerWithTitle:alertTitle message:nil preferredStyle:UIAlertControllerStyleAlert];
     193    UIAlertAction* allowAction = [UIAlertAction actionWithTitle:allowButtonString style:UIAlertActionStyleDefault handler:[completionBlock](UIAlertAction *action) {
     194        completionBlock(true);
     195    }];
     196
     197    UIAlertAction* doNotAllowAction = [UIAlertAction actionWithTitle:doNotAllowButtonString style:UIAlertActionStyleCancel handler:[completionBlock](UIAlertAction *action) {
     198        completionBlock(false);
     199    }];
     200
     201    [alert addAction:doNotAllowAction];
     202    [alert addAction:allowAction];
     203
     204    [[UIViewController _viewControllerForFullScreenPresentationFromView:webView] presentViewController:alert animated:YES completion:nil];
     205#endif
     206}
     207
    114208#if HAVE(AVCAPTUREDEVICE)
    115209
  • trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm

    r269810 r269918  
    13371337    auto delegate = (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get();
    13381338    if (!delegate) {
    1339         completionHandler(false);
     1339        page.requestSpeechRecognitionPermissionByDefaultAction(origin.securityOrigin(), WTFMove(completionHandler));
    13401340        return;
    13411341    }
    13421342
    13431343    if (![delegate respondsToSelector:@selector(_webView:requestSpeechRecognitionPermissionForOrigin:decisionHandler:)]) {
    1344         completionHandler(false);
     1344        page.requestSpeechRecognitionPermissionByDefaultAction(origin.securityOrigin(), WTFMove(completionHandler));
    13451345        return;
    13461346    }
  • trunk/Source/WebKit/UIProcess/MediaPermissionUtilities.h

    r269810 r269918  
    2929#include <wtf/Vector.h>
    3030
     31namespace WebCore {
     32class SecurityOrigin;
     33}
     34
    3135namespace WebKit {
    3236
    33 enum class MediaPermissionType {
    34     Audio,
    35     Video
     37class WebPageProxy;
     38
     39enum class MediaPermissionType : uint8_t {
     40    Audio = 1 << 0,
     41    Video = 1 << 1
    3642};
    3743
     
    4248};
    4349
     50enum class MediaPermissionReason {
     51    UserMedia,
     52    SpeechRecognition,
     53};
     54
    4455#if PLATFORM(COCOA)
    4556bool checkSandboxRequirementForType(MediaPermissionType);
    4657bool checkUsageDescriptionStringForType(MediaPermissionType);
    4758bool checkUsageDescriptionStringForSpeechRecognition();
     59
     60void alertForPermission(WebPageProxy&, MediaPermissionReason, OptionSet<MediaPermissionType>, const WebCore::SecurityOrigin&, CompletionHandler<void(bool)>&&);
    4861#endif
    4962
     
    5972
    6073} // namespace WebKit
    61 
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionPermissionManager.cpp

    r269810 r269918  
    220220}
    221221
     222
     223
     224void SpeechRecognitionPermissionManager::decideByDefaultAction(const WebCore::SecurityOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
     225{
     226#if PLATFORM(COCOA)
     227    OptionSet<MediaPermissionType> type = MediaPermissionType::Audio;
     228    alertForPermission(m_page, MediaPermissionReason::SpeechRecognition, type, origin, WTFMove(completionHandler));
     229#else
     230    completionHandler(false);
     231#endif
     232}
     233
    222234} // namespace WebKit
    223235
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionPermissionManager.h

    r269810 r269918  
    4242    void request(const WebCore::ClientOrigin&, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&&);
    4343
     44    void decideByDefaultAction(const WebCore::SecurityOrigin&, CompletionHandler<void(bool)>&&);
     45
    4446private:
    4547    void startNextRequest();
  • trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.cpp

    r269676 r269918  
    2121#include "UserMediaPermissionRequestProxy.h"
    2222
     23#include "MediaPermissionUtilities.h"
    2324#include "UserMediaPermissionRequestManagerProxy.h"
    2425#include <WebCore/CaptureDeviceManager.h>
     
    9697}
    9798
    98 #if !PLATFORM(COCOA)
    99 void UserMediaPermissionRequestProxy::doDefaultAction()
    100 {
    101     deny();
    102 }
    103 #endif
    104 
    10599void UserMediaPermissionRequestProxy::invalidate()
    106100{
     
    144138}
    145139
     140void UserMediaPermissionRequestProxy::doDefaultAction()
     141{
     142#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
     143    ASSERT(m_manager);
     144    if (!m_manager) {
     145        deny(UserMediaAccessDenialReason::PermissionDenied);
     146        return;
     147    }
     148
     149    if (requiresDisplayCapture()) {
     150        // FIXME: Implement getDisplayMedia prompt, for now deny.
     151        deny(UserMediaAccessDenialReason::PermissionDenied);
     152        return;
     153    }
     154
     155    OptionSet<MediaPermissionType> requestedTypes;
     156    if (requiresAudioCapture())
     157        requestedTypes.add(MediaPermissionType::Audio);
     158    if (requiresVideoCapture())
     159        requestedTypes.add(MediaPermissionType::Video);
     160    alertForPermission(m_manager->page(), MediaPermissionReason::UserMedia, requestedTypes, topLevelDocumentSecurityOrigin(), [this, protectedThis = makeRef(*this)](bool granted) {
     161        if (!granted)
     162            deny(UserMediaAccessDenialReason::PermissionDenied);
     163        else
     164            allow();
     165    });
     166# else
     167    deny();
     168#endif
     169}
     170
    146171} // namespace WebKit
  • trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h

    r269676 r269918  
    8787#if ENABLE(MEDIA_STREAM)
    8888    bool isUserGesturePriviledged() const { return m_request.isUserGesturePriviledged; }
     89#endif
    8990    void doDefaultAction();
    90 #else
    91     NO_RETURN_DUE_TO_ASSERT void doDefaultAction();
    92 #endif
    9391
    9492private:
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r269810 r269918  
    1024910249}
    1025010250
     10251void WebPageProxy::requestSpeechRecognitionPermissionByDefaultAction(const WebCore::SecurityOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
     10252{
     10253    if (!m_speechRecognitionPermissionManager) {
     10254        completionHandler(false);
     10255        return;
     10256    }
     10257
     10258    m_speechRecognitionPermissionManager->decideByDefaultAction(origin, WTFMove(completionHandler));
     10259}
     10260
    1025110261} // namespace WebKit
    1025210262
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r269810 r269918  
    18221822
    18231823    void requestSpeechRecognitionPermission(const WebCore::ClientOrigin&, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&&);
     1824    void requestSpeechRecognitionPermissionByDefaultAction(const WebCore::SecurityOrigin&, CompletionHandler<void(bool)>&&);
    18241825
    18251826private:
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r269907 r269918  
    34693469                411A8DD920DDB6050060D34F /* WKMockMediaDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMockMediaDevice.h; sourceTree = "<group>"; };
    34703470                411A8DDA20DDB6050060D34F /* WKMockMediaDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKMockMediaDevice.cpp; sourceTree = "<group>"; };
    3471                 411A9A9A251DE93E00807D7E /* UserMediaPermissionRequestProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UserMediaPermissionRequestProxy.mm; sourceTree = "<group>"; };
    34723471                411B22621E371244004F7363 /* LibWebRTCNetwork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCNetwork.h; path = Network/webrtc/LibWebRTCNetwork.h; sourceTree = "<group>"; };
    34733472                41287D4B225C05C4009A3E26 /* WebSocketTaskCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebSocketTaskCocoa.mm; sourceTree = "<group>"; };
     
    65276526                                463236852314833F00A48FA7 /* UIRemoteObjectRegistry.h */,
    65286527                                070259BE2522841C00153405 /* UserMediaPermissionRequestManagerProxy.mm */,
    6529                                 411A9A9A251DE93E00807D7E /* UserMediaPermissionRequestProxy.mm */,
    65306528                                52D5A1AA1C57494E00DE34A3 /* VideoFullscreenManagerProxy.h */,
    65316529                                52D5A1AB1C57494E00DE34A3 /* VideoFullscreenManagerProxy.messages.in */,
Note: See TracChangeset for help on using the changeset viewer.