WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-218050-20201022140620.patch (text/plain), 38.32 KB, created by
Aditya Keerthi
on 2020-10-22 11:06:21 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Aditya Keerthi
Created:
2020-10-22 11:06:21 PDT
Size:
38.32 KB
patch
obsolete
>Subversion Revision: 268196 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3304ca304fc39cd0983915f55101934ab4481182..575bdd9311e6d65761a0aec7558ece75474a2f9e 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,53 @@ >+2020-10-21 Aditya Keerthi <akeerthi@apple.com> >+ >+ [Contact Picker API] Implement ContactsManager.select() >+ https://bugs.webkit.org/show_bug.cgi?id=218050 >+ <rdar://problem/69862186> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ ContactsManager.select() is the interface that allows clients to >+ present a contact picker. The method should immediately reject when >+ called from a subframe, when called outside user-interaction and when >+ called while a contact picker is already being displayed. Furthermore, >+ the promise is rejected when the supplied properties are empty or >+ invalid. >+ >+ After the conditions necessary for the UI to be presented are verified, >+ ContactsManager.select() calls into the page's Chrome to display the >+ picker. >+ >+ See https://wicg.github.io/contact-api/spec/#contacts-manager-select >+ for more information. >+ >+ Tests: contact-picker/contacts-select-invalid-properties-and-options.html >+ contact-picker/contacts-select-requires-user-gesture.html >+ contact-picker/contacts-select-subframe.html >+ >+ * Modules/contact-picker/ContactInfo.h: Added encoder and decoder for IPC. >+ (WebCore::ContactInfo::encode const): >+ (WebCore::ContactInfo::decode): >+ * Modules/contact-picker/ContactInfo.idl: >+ * Modules/contact-picker/ContactProperty.h: >+ * Modules/contact-picker/ContactsManager.cpp: >+ (WebCore::ContactsManager::frame const): >+ (WebCore::ContactsManager::select): >+ * Modules/contact-picker/ContactsManager.h: >+ * Modules/contact-picker/ContactsRequestData.h: Added. >+ >+ ContactsRequestData encapsulates the information required to display a >+ picker UI. This includes the requested properties, the URL of the >+ presenting site, and whether multiple contact selection should be allowed. >+ >+ (WebCore::ContactsRequestData::encode const): >+ (WebCore::ContactsRequestData::decode): >+ * WebCore.xcodeproj/project.pbxproj: >+ * page/Chrome.cpp: >+ (WebCore::Chrome::showContactPicker): >+ * page/Chrome.h: >+ * page/ChromeClient.h: >+ (WebCore::ChromeClient::showContactPicker): >+ > 2020-10-20 Aditya Keerthi <akeerthi@apple.com> > > [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index bbb7efc2c13e38bbbf727042e0431bd2ce727643..299ee3b758716cfda2d38f07eccb23e91ea8f072 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,27 @@ >+2020-10-21 Aditya Keerthi <akeerthi@apple.com> >+ >+ [Contact Picker API] Implement ContactsManager.select() >+ https://bugs.webkit.org/show_bug.cgi?id=218050 >+ <rdar://problem/69862186> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added the necessary plumbing in order for the UIProcess to display a >+ contact picker after a call to ContactsManager.select() is made. >+ >+ * UIProcess/PageClient.h: >+ (WebKit::PageClient::showContactPicker): >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::showContactPicker): >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ * WebProcess/WebCoreSupport/WebChromeClient.cpp: >+ (WebKit::WebChromeClient::showContactPicker): >+ * WebProcess/WebCoreSupport/WebChromeClient.h: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::showContactPicker): >+ * WebProcess/WebPage/WebPage.h: >+ > 2020-10-20 Aditya Keerthi <akeerthi@apple.com> > > [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message >diff --git a/Source/WebCore/Modules/contact-picker/ContactInfo.h b/Source/WebCore/Modules/contact-picker/ContactInfo.h >index efd4d43be5eb55dcfd500a17f5ab9a62c97c9f71..12ff514eaf54e31eb583b4b197bd43f960ee7205 100644 >--- a/Source/WebCore/Modules/contact-picker/ContactInfo.h >+++ b/Source/WebCore/Modules/contact-picker/ContactInfo.h >@@ -26,6 +26,7 @@ > #pragma once > > #include <wtf/Forward.h> >+#include <wtf/Optional.h> > #include <wtf/Vector.h> > > namespace WebCore { >@@ -34,6 +35,38 @@ struct ContactInfo { > Vector<String> name; > Vector<String> email; > Vector<String> tel; >+ >+ template<class Encoder> void encode(Encoder&) const; >+ template<class Decoder> static Optional<ContactInfo> decode(Decoder&); > }; > >+template<class Encoder> >+void ContactInfo::encode(Encoder& encoder) const >+{ >+ encoder << name; >+ encoder << email; >+ encoder << tel; > } >+ >+template<class Decoder> >+Optional<ContactInfo> ContactInfo::decode(Decoder& decoder) >+{ >+ Optional<Vector<String>> name; >+ decoder >> name; >+ if (!name) >+ return WTF::nullopt; >+ >+ Optional<Vector<String>> email; >+ decoder >> email; >+ if (!email) >+ return WTF::nullopt; >+ >+ Optional<Vector<String>> tel; >+ decoder >> tel; >+ if (!tel) >+ return WTF::nullopt; >+ >+ return {{ *name, *email, *tel }}; >+} >+ >+} // namespace WebCore >diff --git a/Source/WebCore/Modules/contact-picker/ContactInfo.idl b/Source/WebCore/Modules/contact-picker/ContactInfo.idl >index 16377129c8bd14455504b0a951d6683203005f22..229abfa1dc75278182b35d1ffa74458b83be4494 100644 >--- a/Source/WebCore/Modules/contact-picker/ContactInfo.idl >+++ b/Source/WebCore/Modules/contact-picker/ContactInfo.idl >@@ -25,7 +25,9 @@ > > // https://wicg.github.io/contact-api/ > >-dictionary ContactInfo { >+[ >+ JSGenerateToJSObject, >+] dictionary ContactInfo { > sequence<USVString> name; > sequence<USVString> email; > sequence<USVString> tel; >diff --git a/Source/WebCore/Modules/contact-picker/ContactProperty.h b/Source/WebCore/Modules/contact-picker/ContactProperty.h >index c611b9875bbb22e61e04ae0cb1b95f4898ae5616..90a521766a5970231be8ea087d63b442fa52db10 100644 >--- a/Source/WebCore/Modules/contact-picker/ContactProperty.h >+++ b/Source/WebCore/Modules/contact-picker/ContactProperty.h >@@ -25,8 +25,23 @@ > > #pragma once > >+#include <wtf/EnumTraits.h> >+ > namespace WebCore { > > enum class ContactProperty : uint8_t { Email, Name, Tel }; > > } >+ >+namespace WTF { >+ >+template<> struct EnumTraits<WebCore::ContactProperty> { >+ using values = EnumValues< >+ WebCore::ContactProperty, >+ WebCore::ContactProperty::Email, >+ WebCore::ContactProperty::Name, >+ WebCore::ContactProperty::Tel >+ >; >+}; >+ >+} >diff --git a/Source/WebCore/Modules/contact-picker/ContactsManager.cpp b/Source/WebCore/Modules/contact-picker/ContactsManager.cpp >index af991a5527f8bf686b11bc2535cd1b2a4510c6f5..2aac87a0e57f1503944f5bda2ef58956cb1847f2 100644 >--- a/Source/WebCore/Modules/contact-picker/ContactsManager.cpp >+++ b/Source/WebCore/Modules/contact-picker/ContactsManager.cpp >@@ -26,12 +26,23 @@ > #include "config.h" > #include "ContactsManager.h" > >+#include "Chrome.h" > #include "ContactInfo.h" > #include "ContactProperty.h" >+#include "ContactsRequestData.h" > #include "ContactsSelectOptions.h" >+#include "Document.h" >+#include "Frame.h" >+#include "JSContactInfo.h" > #include "JSDOMPromiseDeferred.h" > #include "Navigator.h" >+#include "Page.h" >+#include "UserGestureIndicator.h" >+#include <wtf/CompletionHandler.h> > #include <wtf/IsoMallocInlines.h> >+#include <wtf/OptionSet.h> >+#include <wtf/Optional.h> >+#include <wtf/URL.h> > > namespace WebCore { > >@@ -49,6 +60,12 @@ ContactsManager::ContactsManager(Navigator& navigator) > > ContactsManager::~ContactsManager() = default; > >+ >+Frame* ContactsManager::frame() const >+{ >+ return m_navigator ? m_navigator->frame() : nullptr; >+} >+ > Navigator* ContactsManager::navigator() > { > return m_navigator.get(); >@@ -62,9 +79,44 @@ void ContactsManager::getProperties(Ref<DeferredPromise>&& promise) > > void ContactsManager::select(const Vector<ContactProperty>& properties, const ContactsSelectOptions& options, Ref<DeferredPromise>&& promise) > { >- UNUSED_PARAM(properties); >- UNUSED_PARAM(options); >- promise->reject(NotSupportedError); >+ auto frame = makeRefPtr(this->frame()); >+ if (!frame || !frame->isMainFrame() || !frame->document() || !frame->page()) { >+ promise->reject(Exception { InvalidStateError }); >+ return; >+ } >+ >+ if (!UserGestureIndicator::processingUserGesture()) { >+ promise->reject(Exception { SecurityError }); >+ return; >+ } >+ >+ if (m_contactPickerIsShowing) { >+ promise->reject(Exception { InvalidStateError }); >+ return; >+ } >+ >+ if (properties.isEmpty()) { >+ promise->reject(TypeError); >+ return; >+ } >+ >+ ContactsRequestData requestData; >+ requestData.multiple = options.multiple; >+ requestData.url = frame->document()->url().string(); >+ for (auto property : properties) >+ requestData.properties.add(property); >+ >+ m_contactPickerIsShowing = true; >+ >+ frame->page()->chrome().showContactPicker(requestData, [promise = WTFMove(promise), this] (Optional<Vector<ContactInfo>>&& info) { >+ m_contactPickerIsShowing = false; >+ if (info) { >+ promise->resolve<IDLSequence<IDLDictionary<ContactInfo>>>(*info); >+ return; >+ } >+ >+ promise->reject(Exception { UnknownError }); >+ }); > } > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/contact-picker/ContactsManager.h b/Source/WebCore/Modules/contact-picker/ContactsManager.h >index 93741234b2eec430f4dae7bb91048f6374a62294..5ef957d530231162fe9ef25c07d2c135d277ef2b 100644 >--- a/Source/WebCore/Modules/contact-picker/ContactsManager.h >+++ b/Source/WebCore/Modules/contact-picker/ContactsManager.h >@@ -33,6 +33,7 @@ > namespace WebCore { > > class DeferredPromise; >+class Frame; > class Navigator; > > enum class ContactProperty : uint8_t; >@@ -45,6 +46,7 @@ public: > static Ref<ContactsManager> create(Navigator&); > ~ContactsManager(); > >+ Frame* frame() const; > Navigator* navigator(); > > void getProperties(Ref<DeferredPromise>&&); >@@ -53,6 +55,7 @@ public: > private: > ContactsManager(Navigator&); > >+ bool m_contactPickerIsShowing { false }; > WeakPtr<Navigator> m_navigator; > }; > >diff --git a/Source/WebCore/Modules/contact-picker/ContactsRequestData.h b/Source/WebCore/Modules/contact-picker/ContactsRequestData.h >new file mode 100644 >index 0000000000000000000000000000000000000000..6d9902112e27d9f9f68a4c433ce53e2c78cf7c5c >--- /dev/null >+++ b/Source/WebCore/Modules/contact-picker/ContactsRequestData.h >@@ -0,0 +1,73 @@ >+/* >+ * Copyright (C) 2020 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "ContactProperty.h" >+#include <wtf/Forward.h> >+#include <wtf/OptionSet.h> >+#include <wtf/Optional.h> >+ >+namespace WebCore { >+ >+struct ContactsRequestData { >+ OptionSet<ContactProperty> properties; >+ bool multiple { false }; >+ String url; >+ >+ template<class Encoder> void encode(Encoder&) const; >+ template<class Decoder> static Optional<ContactsRequestData> decode(Decoder&); >+}; >+ >+template<class Encoder> >+void ContactsRequestData::encode(Encoder& encoder) const >+{ >+ encoder << properties; >+ encoder << multiple; >+ encoder << url; >+} >+ >+template<class Decoder> >+Optional<ContactsRequestData> ContactsRequestData::decode(Decoder& decoder) >+{ >+ Optional<OptionSet<ContactProperty>> properties; >+ decoder >> properties; >+ if (!properties) >+ return WTF::nullopt; >+ >+ Optional<bool> multiple; >+ decoder >> multiple; >+ if (!multiple) >+ return WTF::nullopt; >+ >+ Optional<String> url; >+ decoder >> url; >+ if (!url) >+ return WTF::nullopt; >+ >+ return {{ *properties, *multiple, *url }}; >+} >+ >+} >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index fd74038305f6198d918e368a444fdd782adf9ab7..b38134c64779aac7a22f45167dce794d0e5e2f4d 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -5099,6 +5099,7 @@ > E4E8B4F5216B956500B8834D /* FontCascadeDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E8B4F2216B8B6000B8834D /* FontCascadeDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E4E94D6122FF158A00DD191F /* ComplexLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A1AC7822FAFD500017B75B /* ComplexLineLayout.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ E50620842540919C00C43091 /* ContactsRequestData.h in Headers */ = {isa = PBXBuildFile; fileRef = E50620832540919B00C43091 /* ContactsRequestData.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E516699120FF9918009D2C27 /* ListButtonArrow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E516698F20FF9916009D2C27 /* ListButtonArrow@2x.png */; }; > E517670320B88C1400D41167 /* DataListSuggestionInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = E517670220B88C1400D41167 /* DataListSuggestionInformation.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E51D6A1F24E1E25500891CFA /* DateTimeFieldsState.h in Headers */ = {isa = PBXBuildFile; fileRef = E51D6A1D24E1E25500891CFA /* DateTimeFieldsState.h */; }; >@@ -16111,6 +16112,7 @@ > E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleSheetContents.cpp; sourceTree = "<group>"; }; > E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheetContents.h; sourceTree = "<group>"; }; > E4FB4B35239BEB10003C336A /* LayoutIntegrationInlineContent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutIntegrationInlineContent.cpp; sourceTree = "<group>"; }; >+ E50620832540919B00C43091 /* ContactsRequestData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContactsRequestData.h; sourceTree = "<group>"; }; > E516698F20FF9916009D2C27 /* ListButtonArrow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ListButtonArrow@2x.png"; sourceTree = "<group>"; }; > E517670220B88C1400D41167 /* DataListSuggestionInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataListSuggestionInformation.h; sourceTree = "<group>"; }; > E51A81DE17298D7700BFCA61 /* JSPerformance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformance.cpp; sourceTree = "<group>"; }; >@@ -28602,6 +28604,7 @@ > E596DD2E251903EF00C275A7 /* ContactsManager.cpp */, > E596DD2D251903EF00C275A7 /* ContactsManager.h */, > E596DD2F251903EF00C275A7 /* ContactsManager.idl */, >+ E50620832540919B00C43091 /* ContactsRequestData.h */, > E596DD332519041400C275A7 /* ContactsSelectOptions.h */, > E596DD342519041400C275A7 /* ContactsSelectOptions.idl */, > E596DD28251903D200C275A7 /* Navigator+Contacts.idl */, >@@ -30910,6 +30913,7 @@ > E596DD5D251BB08200C275A7 /* ContactInfo.h in Headers */, > E596DD58251BAC4A00C275A7 /* ContactProperty.h in Headers */, > E596DD30251903EF00C275A7 /* ContactsManager.h in Headers */, >+ E50620842540919C00C43091 /* ContactsRequestData.h in Headers */, > E596DD352519041400C275A7 /* ContactsSelectOptions.h in Headers */, > A818721C0977D3C0005826D9 /* ContainerNode.h in Headers */, > E1A1470811102B1500EEC0F3 /* ContainerNodeAlgorithms.h in Headers */, >diff --git a/Source/WebCore/page/Chrome.cpp b/Source/WebCore/page/Chrome.cpp >index db070bcc7e2660477fc0c6c2580a58bd11ec1189..7c710015572417ef0b369cdd79190edb8c5d163d 100644 >--- a/Source/WebCore/page/Chrome.cpp >+++ b/Source/WebCore/page/Chrome.cpp >@@ -23,6 +23,8 @@ > #include "Chrome.h" > > #include "ChromeClient.h" >+#include "ContactInfo.h" >+#include "ContactsRequestData.h" > #include "DOMWindow.h" > #include "Document.h" > #include "DocumentType.h" >@@ -472,6 +474,11 @@ void Chrome::showShareSheet(ShareDataWithParsedURL& shareData, CompletionHandler > m_client.showShareSheet(shareData, WTFMove(callback)); > } > >+void Chrome::showContactPicker(const ContactsRequestData& requestData, CompletionHandler<void(Optional<Vector<ContactInfo>>&&)>&& callback) >+{ >+ m_client.showContactPicker(requestData, WTFMove(callback)); >+} >+ > void Chrome::loadIconForFiles(const Vector<String>& filenames, FileIconLoader& loader) > { > m_client.loadIconForFiles(filenames, loader); >diff --git a/Source/WebCore/page/Chrome.h b/Source/WebCore/page/Chrome.h >index a5cc1b13bb00221732c769d9e44c2a72470e33f3..06e53426cf3734ecd4e4a6aba1c7915cd7d76378 100644 >--- a/Source/WebCore/page/Chrome.h >+++ b/Source/WebCore/page/Chrome.h >@@ -57,6 +57,8 @@ class PopupMenuClient; > class PopupOpeningObserver; > class SearchPopupMenu; > >+struct ContactInfo; >+struct ContactsRequestData; > struct DateTimeChooserParameters; > struct ShareDataWithParsedURL; > struct ViewportArguments; >@@ -161,6 +163,7 @@ public: > > void runOpenPanel(Frame&, FileChooser&); > void showShareSheet(ShareDataWithParsedURL&, CompletionHandler<void(bool)>&&); >+ void showContactPicker(const ContactsRequestData&, CompletionHandler<void(Optional<Vector<ContactInfo>>&&)>&&); > void loadIconForFiles(const Vector<String>&, FileIconLoader&); > > void dispatchDisabledAdaptationsDidChange(const OptionSet<DisabledAdaptations>&) const; >diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h >index e096732ec5a23a0498298a052eebe50ab14092a8..a6f82f51796e5a858e3bbf08b540bbfb6748eb85 100644 >--- a/Source/WebCore/page/ChromeClient.h >+++ b/Source/WebCore/page/ChromeClient.h >@@ -23,6 +23,7 @@ > > #include "AXObjectCache.h" > #include "AutoplayEvent.h" >+#include "ContactInfo.h" > #include "Cursor.h" > #include "DatabaseDetails.h" > #include "DeviceOrientationOrMotionPermissionState.h" >@@ -113,6 +114,7 @@ class Widget; > class MediaPlayerRequestInstallMissingPluginsCallback; > #endif > >+struct ContactsRequestData; > struct ContentRuleListResults; > struct DateTimeChooserParameters; > struct GraphicsDeviceAdapter; >@@ -302,6 +304,7 @@ public: > > virtual void runOpenPanel(Frame&, FileChooser&) = 0; > virtual void showShareSheet(ShareDataWithParsedURL&, WTF::CompletionHandler<void(bool)>&& callback) { callback(false); } >+ virtual void showContactPicker(const ContactsRequestData&, WTF::CompletionHandler<void(Optional<Vector<ContactInfo>>&&)>&& callback) { callback(WTF::nullopt); } > > // Asynchronous request to load an icon for specified filenames. > virtual void loadIconForFiles(const Vector<String>&, FileIconLoader&) = 0; >diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h >index 5befc4df2001f87a9a7eeb4d687f13e946d703f3..a06c4352ca1073cd3374f90dede52985f278e596 100644 >--- a/Source/WebKit/UIProcess/PageClient.h >+++ b/Source/WebKit/UIProcess/PageClient.h >@@ -35,6 +35,8 @@ > #include "WebPopupMenuProxy.h" > #include <WebCore/ActivityState.h> > #include <WebCore/AlternativeTextClient.h> >+#include <WebCore/ContactInfo.h> >+#include <WebCore/ContactsRequestData.h> > #include <WebCore/DragActions.h> > #include <WebCore/EditorClient.h> > #include <WebCore/FocusDirection.h> >@@ -253,6 +255,7 @@ public: > > virtual bool handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, const FrameInfoData&, API::OpenPanelParameters*, WebOpenPanelResultListenerProxy*) { return false; } > virtual bool showShareSheet(const WebCore::ShareDataWithParsedURL&, WTF::CompletionHandler<void (bool)>&&) { return false; } >+ virtual void showContactPicker(const WebCore::ContactsRequestData&, WTF::CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&& completionHandler) { completionHandler(WTF::nullopt); } > > virtual void didChangeContentSize(const WebCore::IntSize&) = 0; > >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index df4fbf64be7638dafd45c2be9491eff7b3c352bc..d88551ad21b33d8527bcb04b1a10424a42a32224 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5950,6 +5950,12 @@ void WebPageProxy::showShareSheet(const ShareDataWithParsedURL& shareData, Compl > MESSAGE_CHECK(m_process, shareData.files.isEmpty() || m_preferences->webShareFileAPIEnabled()); > pageClient().showShareSheet(shareData, WTFMove(completionHandler)); > } >+ >+void WebPageProxy::showContactPicker(const WebCore::ContactsRequestData& requestData, CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&& completionHandler) >+{ >+ MESSAGE_CHECK(m_process, m_preferences->contactPickerAPIEnabled()); >+ pageClient().showContactPicker(requestData, WTFMove(completionHandler)); >+} > > void WebPageProxy::printFrame(FrameIdentifier frameID, CompletionHandler<void()>&& completionHandler) > { >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index e47cb5e41f39ddb79fd51d751f93aef3dcbc255a..c5432b38561b7ca61ba0eca07894509a7a2884d5 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -243,6 +243,8 @@ struct ApplicationManifest; > struct AttributedString; > struct BackForwardItemIdentifier; > struct CompositionHighlight; >+struct ContactInfo; >+struct ContactsRequestData; > struct ContentRuleListResults; > struct DataListSuggestionInformation; > struct DateTimeChooserParameters; >@@ -1949,6 +1951,7 @@ private: > void runOpenPanel(WebCore::FrameIdentifier, FrameInfoData&&, const WebCore::FileChooserSettings&); > bool didChooseFilesForOpenPanelWithImageTranscoding(const Vector<String>& fileURLs, const Vector<String>& allowedMIMETypes); > void showShareSheet(const WebCore::ShareDataWithParsedURL&, CompletionHandler<void(bool)>&&); >+ void showContactPicker(const WebCore::ContactsRequestData&, CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&&); > void printFrame(WebCore::FrameIdentifier, CompletionHandler<void()>&&); > void exceededDatabaseQuota(WebCore::FrameIdentifier, const String& originIdentifier, const String& databaseName, const String& displayName, uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, Messages::WebPageProxy::ExceededDatabaseQuotaDelayedReply&&); > void reachedApplicationCacheOriginQuota(const String& originIdentifier, uint64_t currentQuota, uint64_t totalBytesNeeded, Messages::WebPageProxy::ReachedApplicationCacheOriginQuotaDelayedReply&&); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in >index 42145f2c5c04b338ab041fb06d69686c2f579152..0944a9038a1ab1789fdecf86b107e27f130013ec 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in >@@ -69,6 +69,7 @@ messages -> WebPageProxy { > PageDidScroll() > RunOpenPanel(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, struct WebCore::FileChooserSettings parameters) > ShowShareSheet(struct WebCore::ShareDataWithParsedURL shareData) -> (bool granted) Async >+ ShowContactPicker(struct WebCore::ContactsRequestData requestData) -> (Optional<Vector<WebCore::ContactInfo>> info) Async > PrintFrame(WebCore::FrameIdentifier frameID) -> () Synchronous > RunModal() > NotifyScrollerThumbIsVisibleInRect(WebCore::IntRect scrollerThumb) >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >index 76c0d1fc8aa090dde462cb21e24a234f100acfe1..708a5f29cbc8aef5b5ce5186e2fd3f273a87f909 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp >@@ -822,6 +822,11 @@ void WebChromeClient::showShareSheet(ShareDataWithParsedURL& shareData, Completi > m_page.showShareSheet(shareData, WTFMove(callback)); > } > >+void WebChromeClient::showContactPicker(const WebCore::ContactsRequestData& requestData, WTF::CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&& callback) >+{ >+ m_page.showContactPicker(requestData, WTFMove(callback)); >+} >+ > void WebChromeClient::loadIconForFiles(const Vector<String>& filenames, FileIconLoader& loader) > { > loader.iconLoaded(createIconForFiles(filenames)); >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h >index 46f0e9ae5bfa54a137e3bb42563e2bac1725f6c8..23cc403a7baaed5863261fd572fecdd73d25df21 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h >@@ -200,6 +200,7 @@ private: > > void runOpenPanel(WebCore::Frame&, WebCore::FileChooser&) final; > void showShareSheet(WebCore::ShareDataWithParsedURL&, WTF::CompletionHandler<void(bool)>&&) final; >+ void showContactPicker(const WebCore::ContactsRequestData&, WTF::CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&&) final; > void loadIconForFiles(const Vector<String>&, WebCore::FileIconLoader&) final; > > void setCursor(const WebCore::Cursor&) final; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index 260a0e2acb4be9ea7b3d0f3abcfd0602f51472b5..d648c3c9ec497a66b74a9a8c47a0704557514e32 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -148,6 +148,7 @@ > #include <WebCore/BackForwardController.h> > #include <WebCore/Chrome.h> > #include <WebCore/CommonVM.h> >+#include <WebCore/ContactsRequestData.h> > #include <WebCore/ContextMenuController.h> > #include <WebCore/DOMPasteAccess.h> > #include <WebCore/DataTransfer.h> >@@ -6894,6 +6895,11 @@ void WebPage::showShareSheet(ShareDataWithParsedURL& shareData, WTF::CompletionH > sendWithAsyncReply(Messages::WebPageProxy::ShowShareSheet(WTFMove(shareData)), WTFMove(callback)); > } > >+void WebPage::showContactPicker(const WebCore::ContactsRequestData& requestData, CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&& callback) >+{ >+ sendWithAsyncReply(Messages::WebPageProxy::ShowContactPicker(requestData), WTFMove(callback)); >+} >+ > WebCore::DOMPasteAccessResponse WebPage::requestDOMPasteAccess(const String& originIdentifier) > { > auto response = WebCore::DOMPasteAccessResponse::DeniedForGesture; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h >index 1ff35fb0936a5c7716aa4c012d26e073b4478e95..02a5fae3762272421d98673453b1d07c8e9c69a0 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -213,6 +213,8 @@ struct AttributedString; > struct BackForwardItemIdentifier; > struct CompositionHighlight; > struct CompositionUnderline; >+struct ContactInfo; >+struct ContactsRequestData; > struct DictationAlternative; > struct ElementContext; > struct GlobalFrameIdentifier; >@@ -1240,6 +1242,7 @@ public: > #endif > > void showShareSheet(WebCore::ShareDataWithParsedURL&, CompletionHandler<void(bool)>&& callback); >+ void showContactPicker(const WebCore::ContactsRequestData&, CompletionHandler<void(Optional<Vector<WebCore::ContactInfo>>&&)>&&); > > #if ENABLE(ATTACHMENT_ELEMENT) > void insertAttachment(const String& identifier, Optional<uint64_t>&& fileSize, const String& fileName, const String& contentType, CallbackID); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index a6e5139d39ec008c296292636495f4612c0645bd..64fc6ccb29253af64d36abedc65d5491a1702e36 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,23 @@ >+2020-10-21 Aditya Keerthi <akeerthi@apple.com> >+ >+ [Contact Picker API] Implement ContactsManager.select() >+ https://bugs.webkit.org/show_bug.cgi?id=218050 >+ <rdar://problem/69862186> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added tests for failure cases of the API. Note that success cases are >+ untested since no platforms currently display a picker UI, and the >+ specification states that the promise should fail in this case. The >+ success test cases will be added once the UI is implemented for iOS. >+ >+ * contact-picker/contacts-select-invalid-properties-and-options-expected.txt: Added. >+ * contact-picker/contacts-select-invalid-properties-and-options.html: Added. >+ * contact-picker/contacts-select-requires-user-gesture-expected.txt: Added. >+ * contact-picker/contacts-select-requires-user-gesture.html: Added. >+ * contact-picker/contacts-select-subframe-expected.txt: Added. >+ * contact-picker/contacts-select-subframe.html: Added. >+ > 2020-10-20 Aditya Keerthi <akeerthi@apple.com> > > [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message >diff --git a/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options-expected.txt b/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..8b2ad1ded6587a1dc17673fbc9be859580e6e8d6 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options-expected.txt >@@ -0,0 +1,34 @@ >+This test verifies that navigator.contacts.select fails if invalid properties or options are specified. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+Calling navigator.contacts.select(). >+PASS Invalid properties and/or options specified. >+PASS exception.name is "TypeError" >+PASS finishedSubtest became true >+ >+Calling navigator.contacts.select(). >+PASS Invalid properties and/or options specified. >+PASS exception.name is "TypeError" >+PASS finishedSubtest became true >+ >+Calling navigator.contacts.select(). >+PASS Invalid properties and/or options specified. >+PASS exception.name is "TypeError" >+PASS finishedSubtest became true >+ >+Calling navigator.contacts.select(). >+PASS Invalid properties and/or options specified. >+PASS exception.name is "TypeError" >+PASS finishedSubtest became true >+ >+Calling navigator.contacts.select(). >+PASS Invalid properties and/or options specified. >+PASS exception.name is "TypeError" >+PASS finishedSubtest became true >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+Show contacts >diff --git a/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options.html b/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options.html >new file mode 100644 >index 0000000000000000000000000000000000000000..53ae9af9a49bb6160086a2e966c1aed5af124d80 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-invalid-properties-and-options.html >@@ -0,0 +1,52 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ experimental:ContactPickerAPIEnabled=true ] --> >+<html> >+ <head> >+ <script src="../resources/js-test.js"></script> >+ <script src="../resources/ui-helper.js"></script> >+ </head> >+ <script> >+ jsTestIsAsync = true; >+ finishedSubtest = false; >+ >+ async function testContactsSelectWithPropertiesAndOptions(properties, options = {}) >+ { >+ finishedSubtest = false; >+ debug("Calling navigator.contacts.select()."); >+ >+ const contactsButton = document.getElementById("contacts"); >+ contactsButton.addEventListener("click", async () => { >+ try { >+ await navigator.contacts.select(properties, options); >+ testFailed("navigator.contacts.select succeeded with invalid properties and/or options."); >+ } catch (exception) { >+ window.exception = exception; >+ testPassed("Invalid properties and/or options specified."); >+ shouldBeEqualToString("exception.name", "TypeError"); >+ } >+ >+ finishedSubtest = true; >+ }, { once: true }); >+ >+ await UIHelper.activateElement(contactsButton); >+ await new Promise(resolve => shouldBecomeEqual("finishedSubtest", "true", resolve)); >+ >+ debug(""); >+ } >+ >+ async function runTest() >+ { >+ description("This test verifies that navigator.contacts.select fails if invalid properties or options are specified.\n"); >+ >+ await testContactsSelectWithPropertiesAndOptions([]); >+ await testContactsSelectWithPropertiesAndOptions(["Invalid"]); >+ await testContactsSelectWithPropertiesAndOptions("String"); >+ await testContactsSelectWithPropertiesAndOptions([23]); >+ await testContactsSelectWithPropertiesAndOptions(["name", "email"], 50); >+ >+ finishJSTest(); >+ } >+ </script> >+ <body onload=runTest()> >+ <button id="contacts">Show contacts</button> >+ </body> >+</html> >diff --git a/LayoutTests/contact-picker/contacts-select-requires-user-gesture-expected.txt b/LayoutTests/contact-picker/contacts-select-requires-user-gesture-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..fe08334323e2b8f568f3e321f94a26b2ad99fe00 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-requires-user-gesture-expected.txt >@@ -0,0 +1,11 @@ >+This test verifies that navigator.contacts.select requires a user gesture. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS Did not present contact picker. >+PASS exception.name is "SecurityError" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/contact-picker/contacts-select-requires-user-gesture.html b/LayoutTests/contact-picker/contacts-select-requires-user-gesture.html >new file mode 100644 >index 0000000000000000000000000000000000000000..8709564083bf051fc67b8f57d6c85d1e1ad1b060 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-requires-user-gesture.html >@@ -0,0 +1,26 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ experimental:ContactPickerAPIEnabled=true ] --> >+<html> >+ <head> >+ <script src="../resources/js-test.js"></script> >+ </head> >+ <script> >+ jsTestIsAsync = true; >+ >+ async function runTest() >+ { >+ description("This test verifies that navigator.contacts.select requires a user gesture."); >+ >+ try { >+ await navigator.contacts.select(["name", "email", "tel"]); >+ testFailed("Presented contact picker without user gesture."); >+ } catch (exception) { >+ window.exception = exception; >+ testPassed("Did not present contact picker."); >+ shouldBeEqualToString("exception.name", "SecurityError"); >+ } >+ >+ finishJSTest(); >+ } >+ </script> >+ <body onload=runTest()></body> >+</html> >diff --git a/LayoutTests/contact-picker/contacts-select-subframe-expected.txt b/LayoutTests/contact-picker/contacts-select-subframe-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..3403a25f26f0eedb052f738e5529921ded207d61 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-subframe-expected.txt >@@ -0,0 +1,10 @@ >+This test verifies that navigator.contacts.select fails if called from a subframe. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS Did not present contact picker. >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/contact-picker/contacts-select-subframe.html b/LayoutTests/contact-picker/contacts-select-subframe.html >new file mode 100644 >index 0000000000000000000000000000000000000000..9d304f68c9b04f6dcefc979fa0c6725de79bd7a5 >--- /dev/null >+++ b/LayoutTests/contact-picker/contacts-select-subframe.html >@@ -0,0 +1,45 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ experimental:ContactPickerAPIEnabled=true ] --> >+<html> >+ <head> >+ <script src="../resources/js-test.js"></script> >+ <script src="../resources/ui-helper.js"></script> >+ </head> >+ <script> >+ jsTestIsAsync = true; >+ >+ async function runTest() >+ { >+ description("This test verifies that navigator.contacts.select fails if called from a subframe."); >+ >+ window.addEventListener("message", (event) => { >+ if (event.data === "didClickOnContactsButtonAndFailedToSelect") { >+ testPassed("Did not present contact picker."); >+ finishJSTest(); >+ } >+ }); >+ >+ frame = document.querySelector("iframe"); >+ >+ await UIHelper.activateElement(frame); >+ } >+ </script> >+ <body onload=runTest()> >+ <iframe srcdoc=" >+ <body> >+ <button style='width: 100%; height: 134px;'>Show contacts</button> >+ <script> >+ const button = document.querySelector('button'); >+ button.addEventListener('click', async () => { >+ try { >+ await navigator.contacts.select(['name']); >+ } catch (exception) { >+ if (exception.name === 'InvalidStateError') { >+ parent.postMessage('didClickOnContactsButtonAndFailedToSelect', '*'); >+ } >+ } >+ }); >+ </script> >+ </body> >+ "></iframe> >+ </body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 218050
:
412026
|
412031
|
412116
|
412132
|
412134