Changeset 271381 in webkit


Ignore:
Timestamp:
Jan 11, 2021 2:29:21 PM (18 months ago)
Author:
commit-queue@webkit.org
Message:

Make SpeechRecognition permission error more informative
https://bugs.webkit.org/show_bug.cgi?id=220436

Patch by Sihui Liu <sihui_liu@appe.com> on 2021-01-11
Reviewed by Youenn Fablet.

Source/WebKit:

Make SpeechRecognitionPermissionManager complete requests with an optional SpeechRecognitionError instead of a
boolean value.

  • UIProcess/SpeechRecognitionPermissionManager.cpp:

(WebKit::SpeechRecognitionPermissionManager::~SpeechRecognitionPermissionManager):
(WebKit::SpeechRecognitionPermissionManager::request):
(WebKit::SpeechRecognitionPermissionManager::startProcessingRequest):
(WebKit::SpeechRecognitionPermissionManager::continueProcessingRequest):
(WebKit::SpeechRecognitionPermissionManager::completeCurrentRequest):
(WebKit::SpeechRecognitionPermissionManager::requestSpeechRecognitionServiceAccess):
(WebKit::SpeechRecognitionPermissionManager::requestMicrophoneAccess):
(WebKit::SpeechRecognitionPermissionManager::requestUserPermission):

  • UIProcess/SpeechRecognitionPermissionManager.h:
  • UIProcess/SpeechRecognitionPermissionRequest.h:

(WebKit::SpeechRecognitionPermissionRequest::create):
(WebKit::SpeechRecognitionPermissionRequest::complete):
(WebKit::SpeechRecognitionPermissionRequest::SpeechRecognitionPermissionRequest):

  • UIProcess/SpeechRecognitionServer.cpp:

(WebKit::SpeechRecognitionServer::requestPermissionForRequest):

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

(WebKit::WebPageProxy::requestSpeechRecognitionPermission):

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

(WebKit::WebProcessProxy::createSpeechRecognitionServer):

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm:

(TestWebKitAPI::TEST):

LayoutTests:

  • fast/speechrecognition/permission-error-expected.txt:
  • fast/speechrecognition/permission-error.html:
Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r271379 r271381  
     12021-01-11  Sihui Liu  <sihui_liu@appe.com>
     2
     3        Make SpeechRecognition permission error more informative
     4        https://bugs.webkit.org/show_bug.cgi?id=220436
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * fast/speechrecognition/permission-error-expected.txt:
     9        * fast/speechrecognition/permission-error.html:
     10
    1112021-01-11  Sihui Liu  <sihui_liu@appe.com>
    212
  • trunk/LayoutTests/fast/speechrecognition/permission-error-expected.txt

    r270868 r271381  
    77PASS recognition.start() did not throw exception.
    88PASS event.error is "not-allowed"
    9 PASS event.message is "Permission check failed"
     9PASS event.message is "User permission check has failed"
    1010PASS successfullyParsed is true
    1111
  • trunk/LayoutTests/fast/speechrecognition/permission-error.html

    r270868 r271381  
    1515recognition.onerror = (event) => {
    1616    shouldBeEqualToString("event.error", "not-allowed");
    17     shouldBeEqualToString("event.message", "Permission check failed");
     17    shouldBeEqualToString("event.message", "User permission check has failed");
    1818
    1919    finishJSTest();
  • trunk/Source/WebKit/ChangeLog

    r271378 r271381  
     12021-01-11  Sihui Liu  <sihui_liu@appe.com>
     2
     3        Make SpeechRecognition permission error more informative
     4        https://bugs.webkit.org/show_bug.cgi?id=220436
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Make SpeechRecognitionPermissionManager complete requests with an optional SpeechRecognitionError instead of a
     9        boolean value.
     10
     11        * UIProcess/SpeechRecognitionPermissionManager.cpp:
     12        (WebKit::SpeechRecognitionPermissionManager::~SpeechRecognitionPermissionManager):
     13        (WebKit::SpeechRecognitionPermissionManager::request):
     14        (WebKit::SpeechRecognitionPermissionManager::startProcessingRequest):
     15        (WebKit::SpeechRecognitionPermissionManager::continueProcessingRequest):
     16        (WebKit::SpeechRecognitionPermissionManager::completeCurrentRequest):
     17        (WebKit::SpeechRecognitionPermissionManager::requestSpeechRecognitionServiceAccess):
     18        (WebKit::SpeechRecognitionPermissionManager::requestMicrophoneAccess):
     19        (WebKit::SpeechRecognitionPermissionManager::requestUserPermission):
     20        * UIProcess/SpeechRecognitionPermissionManager.h:
     21        * UIProcess/SpeechRecognitionPermissionRequest.h:
     22        (WebKit::SpeechRecognitionPermissionRequest::create):
     23        (WebKit::SpeechRecognitionPermissionRequest::complete):
     24        (WebKit::SpeechRecognitionPermissionRequest::SpeechRecognitionPermissionRequest):
     25        * UIProcess/SpeechRecognitionServer.cpp:
     26        (WebKit::SpeechRecognitionServer::requestPermissionForRequest):
     27        * UIProcess/SpeechRecognitionServer.h:
     28        * UIProcess/WebPageProxy.cpp:
     29        (WebKit::WebPageProxy::requestSpeechRecognitionPermission):
     30        * UIProcess/WebPageProxy.h:
     31        * UIProcess/WebProcessProxy.cpp:
     32        (WebKit::WebProcessProxy::createSpeechRecognitionServer):
     33
    1342021-01-11  Alex Christensen  <achristensen@webkit.org>
    235
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionPermissionManager.cpp

    r271205 r271381  
    7373{
    7474    for (auto& request : m_requests)
    75         request->complete(SpeechRecognitionPermissionDecision::Deny);
     75        request->complete(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Permission manager has exited"_s });
    7676}
    7777   
    78 void SpeechRecognitionPermissionManager::request(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&& completiontHandler)
     78void SpeechRecognitionPermissionManager::request(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(Optional<SpeechRecognitionError>&&)>&& completiontHandler)
    7979{
    8080    m_requests.append(SpeechRecognitionPermissionRequest::create(lang, origin, WTFMove(completiontHandler)));
     
    9595#if PLATFORM(COOCA)
    9696    if (!checkSandboxRequirementForType(MediaPermissionType::Audio)) {
    97         completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
    98         return;
    99     }
    100 #endif
    101 
    102     // TCC status may have changed between requests.
    103     m_microphoneCheck = computeMicrophoneAccess();
    104     m_speechRecognitionServiceCheck = computeSpeechRecognitionServiceAccess();
     97        completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Sandbox check has failed"_s });
     98        return;
     99    }
     100#endif
    105101
    106102    m_page.syncIfMockDevicesEnabledChanged();
    107     bool mockCaptureDevicesEnabled = m_page.preferences().mockCaptureDevicesEnabled();
    108     if (mockCaptureDevicesEnabled) {
     103    if (m_page.preferences().mockCaptureDevicesEnabled()) {
    109104        m_microphoneCheck = CheckResult::Granted;
    110105        m_speechRecognitionServiceCheck = CheckResult::Granted;
    111     }
     106    } else {
     107        // TCC status may have changed between requests.
     108        m_microphoneCheck = computeMicrophoneAccess();
     109        if (m_microphoneCheck == CheckResult::Denied) {
     110            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Microphone permission check has failed"_s });
     111            return;
     112        }
     113
     114        m_speechRecognitionServiceCheck = computeSpeechRecognitionServiceAccess();
     115        if (m_speechRecognitionServiceCheck == CheckResult::Denied) {
     116            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::ServiceNotAllowed, "Speech recognition service permission check has failed"_s });
     117            return;
     118        }
    112119
    113120#if HAVE(SPEECHRECOGNIZER)
    114     if (!mockCaptureDevicesEnabled && m_speechRecognitionServiceCheck != CheckResult::Denied) {
    115         // Speech recognition service can be unavailable when user does not enable dictation in system settings.
    116         // Let's avoid prompting user in that case.
    117         if (!checkSpeechRecognitionServiceAvailability(m_requests.first()->lang()))
    118             m_speechRecognitionServiceCheck = CheckResult::Denied;
    119     }
    120 #endif
    121 
    122     if (m_microphoneCheck == CheckResult::Denied || m_speechRecognitionServiceCheck == CheckResult::Denied) {
    123         completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
    124         return;
     121        if (!checkSpeechRecognitionServiceAvailability(m_requests.first()->lang())) {
     122            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::ServiceNotAllowed, "Speech recognition service is not available"_s });
     123            return;
     124        }
     125#endif
    125126    }
    126127
     
    135136
    136137    if (m_userPermissionCheck == CheckResult::Denied) {
    137         completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
     138        completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "User permission check has failed"_s });
    138139        return;
    139140    }
     
    163164
    164165    if (!m_page.isViewVisible()) {
    165         completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
    166         return;
    167     }
    168 
    169     completeCurrentRequest(SpeechRecognitionPermissionDecision::Grant);
    170 }
    171 
    172 void SpeechRecognitionPermissionManager::completeCurrentRequest(SpeechRecognitionPermissionDecision decision)
     166        completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Page is not visible to user" });
     167        return;
     168    }
     169
     170    completeCurrentRequest();
     171}
     172
     173void SpeechRecognitionPermissionManager::completeCurrentRequest(Optional<SpeechRecognitionError>&& error)
    173174{
    174175    ASSERT(!m_requests.isEmpty());
    175176    auto currentRequest = m_requests.takeFirst();
    176     currentRequest->complete(decision);
     177    currentRequest->complete(WTFMove(error));
    177178
    178179    startNextRequest();
     
    190191        m_speechRecognitionServiceCheck = authorized ? CheckResult::Granted : CheckResult::Denied;
    191192        if (m_speechRecognitionServiceCheck == CheckResult::Denied) {
    192             completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
     193            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::ServiceNotAllowed, "Speech recognition service permission check has failed"_s });
    193194            return;
    194195        }
     
    210211        m_microphoneCheck = authorized ? CheckResult::Granted : CheckResult::Denied;
    211212        if (m_microphoneCheck == CheckResult::Denied) {
    212             completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
     213            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Microphone permission check has failed"_s });
    213214            return;
    214215        }
     
    232233        m_userPermissionCheck = granted ? CheckResult::Granted : CheckResult::Denied;
    233234        if (m_userPermissionCheck == CheckResult::Denied) {
    234             completeCurrentRequest(SpeechRecognitionPermissionDecision::Deny);
     235            completeCurrentRequest(SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "User permission check has failed"_s });
    235236            return;
    236237        }
     
    240241    m_page.uiClient().decidePolicyForSpeechRecognitionPermissionRequest(m_page, API::SecurityOrigin::create(topOrigin.get()).get(), WTFMove(decisionHandler));
    241242}
    242 
    243 
    244243
    245244void SpeechRecognitionPermissionManager::decideByDefaultAction(const WebCore::SecurityOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionPermissionManager.h

    r271154 r271381  
    4040    explicit SpeechRecognitionPermissionManager(WebPageProxy&);
    4141    ~SpeechRecognitionPermissionManager();
    42     void request(const String& lang, const WebCore::ClientOrigin&, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&&);
     42    void request(const String& lang, const WebCore::ClientOrigin&, CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)>&&);
    4343
    4444    void decideByDefaultAction(const WebCore::SecurityOrigin&, CompletionHandler<void(bool)>&&);
     
    4949    void startProcessingRequest();
    5050    void continueProcessingRequest();
    51     void completeCurrentRequest(SpeechRecognitionPermissionDecision);
     51    void completeCurrentRequest(Optional<WebCore::SpeechRecognitionError>&& = WTF::nullopt);
    5252    void requestMicrophoneAccess();
    5353    void requestSpeechRecognitionServiceAccess();
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionPermissionRequest.h

    r271031 r271381  
    2828#include "APIObject.h"
    2929#include <WebCore/ClientOrigin.h>
     30#include <WebCore/SpeechRecognitionError.h>
    3031#include <wtf/CompletionHandler.h>
    3132
    3233namespace WebKit {
    3334
    34 enum class SpeechRecognitionPermissionDecision : bool { Deny, Grant };
    35 
    3635class SpeechRecognitionPermissionRequest : public RefCounted<SpeechRecognitionPermissionRequest> {
    3736public:
    38     static Ref<SpeechRecognitionPermissionRequest> create(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&& completionHandler)
     37    static Ref<SpeechRecognitionPermissionRequest> create(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)>&& completionHandler)
    3938    {
    4039        return adoptRef(*new SpeechRecognitionPermissionRequest(lang, origin, WTFMove(completionHandler)));
    4140    }
    4241
    43     void complete(SpeechRecognitionPermissionDecision decision)
     42    void complete(Optional<WebCore::SpeechRecognitionError>&& error)
    4443    {
    4544        auto completionHandler = std::exchange(m_completionHandler, { });
    46         completionHandler(decision);
     45        completionHandler(WTFMove(error));
    4746    }
    4847
     
    5150
    5251private:
    53     SpeechRecognitionPermissionRequest(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&& completionHandler)
     52    SpeechRecognitionPermissionRequest(const String& lang, const WebCore::ClientOrigin& origin, CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)>&& completionHandler)
    5453        : m_lang(lang)
    5554        , m_origin(origin)
     
    5958    String m_lang;
    6059    WebCore::ClientOrigin m_origin;
    61     CompletionHandler<void(SpeechRecognitionPermissionDecision)> m_completionHandler;
     60    CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)> m_completionHandler;
    6261};
    6362
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionServer.cpp

    r271205 r271381  
    6565void SpeechRecognitionServer::requestPermissionForRequest(WebCore::SpeechRecognitionRequest& request)
    6666{
    67     m_permissionChecker(request.lang(), request.clientOrigin(), [this, weakThis = makeWeakPtr(this), weakRequest = makeWeakPtr(request)](auto decision) mutable {
     67    m_permissionChecker(request.lang(), request.clientOrigin(), [this, weakThis = makeWeakPtr(this), weakRequest = makeWeakPtr(request)](auto error) mutable {
    6868        if (!weakThis)
    6969            return;
     
    7373
    7474        auto identifier = weakRequest->clientIdentifier();
    75         if (decision == SpeechRecognitionPermissionDecision::Deny) {
     75        if (error) {
    7676            m_requests.remove(identifier);
    77             auto error = WebCore::SpeechRecognitionError { WebCore::SpeechRecognitionErrorType::NotAllowed, "Permission check failed"_s };
    78             sendUpdate(identifier, WebCore::SpeechRecognitionUpdateType::Error, error);
     77            sendUpdate(identifier, WebCore::SpeechRecognitionUpdateType::Error, WTFMove(error));
    7978            return;
    8079        }
  • trunk/Source/WebKit/UIProcess/SpeechRecognitionServer.h

    r271205 r271381  
    4444
    4545class WebProcessProxy;
    46 enum class SpeechRecognitionPermissionDecision : bool;
    4746
    4847using SpeechRecognitionServerIdentifier = WebCore::PageIdentifier;
    49 using SpeechRecognitionPermissionChecker = Function<void(const String&, const WebCore::ClientOrigin&, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&&)>;
     48using SpeechRecognitionPermissionChecker = Function<void(const String&, const WebCore::ClientOrigin&, CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)>&&)>;
    5049using SpeechRecognitionCheckIfMockSpeechRecognitionEnabled = Function<bool()>;
    5150
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r271378 r271381  
    1030210302}
    1030310303
    10304 void WebPageProxy::requestSpeechRecognitionPermission(const String& lang, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&& completionHandler)
     10304void WebPageProxy::requestSpeechRecognitionPermission(const String& lang, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void(Optional<SpeechRecognitionError>&&)>&& completionHandler)
    1030510305{
    1030610306    if (!m_speechRecognitionPermissionManager)
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r271378 r271381  
    265265struct SecurityOriginData;
    266266struct ShareData;
     267struct SpeechRecognitionError;
    267268struct TextAlternativeWithRange;
    268269struct TextCheckingResult;
     
    368369enum class NegotiatedLegacyTLS : bool;
    369370enum class ProcessSwapRequestedByClient : bool;
    370 enum class SpeechRecognitionPermissionDecision : bool;
    371371enum class UndoOrRedo : bool;
    372372enum class WebContentMode : uint8_t;
     
    18111811    size_t suspendMediaPlaybackCounter() { return m_suspendMediaPlaybackCounter; }
    18121812
    1813     void requestSpeechRecognitionPermission(const String& lang, const WebCore::ClientOrigin&, CompletionHandler<void(SpeechRecognitionPermissionDecision)>&&);
     1813    void requestSpeechRecognitionPermission(const String& lang, const WebCore::ClientOrigin&, CompletionHandler<void(Optional<WebCore::SpeechRecognitionError>&&)>&&);
    18141814    void requestSpeechRecognitionPermissionByDefaultAction(const WebCore::SecurityOrigin&, CompletionHandler<void(bool)>&&);
    18151815
  • trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp

    r271238 r271381  
    17251725    auto permissionChecker = [weakPage = makeWeakPtr(targetPage)](auto& lang, auto& origin, auto&& completionHandler) mutable {
    17261726        if (!weakPage) {
    1727             completionHandler(SpeechRecognitionPermissionDecision::Deny);
     1727            completionHandler(WebCore::SpeechRecognitionError { SpeechRecognitionErrorType::NotAllowed, "Page no longer exists"_s });
    17281728            return;
    17291729        }
  • trunk/Tools/ChangeLog

    r271380 r271381  
     12021-01-11  Sihui Liu  <sihui_liu@appe.com>
     2
     3        Make SpeechRecognition permission error more informative
     4        https://bugs.webkit.org/show_bug.cgi?id=220436
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm:
     9        (TestWebKitAPI::TEST):
     10
    1112021-01-11  Wenson Hsieh  <wenson_hsieh@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm

    r271311 r271381  
    120120    [webView loadTestPageNamed:@"speechrecognition-user-permission-persistence"];
    121121    TestWebKitAPI::Util::run(&receivedScriptMessage);
    122     EXPECT_WK_STREQ(@"Error: not-allowed - Permission check failed", [lastScriptMessage body]);
     122    EXPECT_WK_STREQ(@"Error: not-allowed - User permission check has failed", [lastScriptMessage body]);
    123123    EXPECT_TRUE(permissionRequested);
    124124
     
    128128    [webView stringByEvaluatingJavaScript:@"start()"];
    129129    TestWebKitAPI::Util::run(&receivedScriptMessage);
    130     EXPECT_WK_STREQ(@"Error: not-allowed - Permission check failed", [lastScriptMessage body]);
     130    EXPECT_WK_STREQ(@"Error: not-allowed - User permission check has failed", [lastScriptMessage body]);
    131131    EXPECT_FALSE(permissionRequested);
    132132
     
    232232    [webView evaluateJavaScript:@"start()" completionHandler:nil];
    233233    TestWebKitAPI::Util::run(&receivedScriptMessage);
    234     EXPECT_WK_STREQ(@"Error: not-allowed - Permission check failed", [lastScriptMessage body]);
     234    EXPECT_WK_STREQ(@"Error: not-allowed - Page is not visible to user", [lastScriptMessage body]);
    235235}
    236236
Note: See TracChangeset for help on using the changeset viewer.