Commit 9d32f659 authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Contacts] Update implementation to match spec changes.

- Expose the `address` property and place it behind a flag.
- Add & implement the getProperties method.

Change-Id: If9bbebde6b8d076fd48b0b8a3584181e40adc1d4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1835621Reviewed-by: default avatarStephen White <senorblanco@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702810}
parent f2b9766e
...@@ -2425,6 +2425,7 @@ enum WebFeature { ...@@ -2425,6 +2425,7 @@ enum WebFeature {
kFragmentHasTildeAtTilde = 3041, kFragmentHasTildeAtTilde = 3041,
kFragmentHasAmpersandDelimiterQuestion = 3042, kFragmentHasAmpersandDelimiterQuestion = 3042,
kInvalidFragmentDirective = 3043, kInvalidFragmentDirective = 3043,
kContactsManagerGetProperties = 3044,
// Add new features immediately above this line. Don't change assigned // Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots. // numbers of any item, and don't reuse removed slots.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/contacts_picker/contacts_manager.h" #include "third_party/blink/renderer/modules/contacts_picker/contacts_manager.h"
#include "base/stl_util.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document.h"
...@@ -64,8 +65,23 @@ TypeConverter<blink::ContactInfo*, blink::mojom::blink::ContactInfoPtr>:: ...@@ -64,8 +65,23 @@ TypeConverter<blink::ContactInfo*, blink::mojom::blink::ContactInfoPtr>::
} // namespace mojo } // namespace mojo
namespace blink { namespace blink {
namespace {
// ContactProperty enum strings.
constexpr char kAddress[] = "address";
constexpr char kEmail[] = "email";
constexpr char kName[] = "name";
constexpr char kTel[] = "tel";
} // namespace
ContactsManager::ContactsManager() {
properties_ = {kEmail, kName, kTel};
if (RuntimeEnabledFeatures::ContactsManagerAddressesEnabled())
properties_.push_back(kAddress);
}
ContactsManager::ContactsManager() = default;
ContactsManager::~ContactsManager() = default; ContactsManager::~ContactsManager() = default;
mojo::Remote<mojom::blink::ContactsManager>& mojo::Remote<mojom::blink::ContactsManager>&
...@@ -113,22 +129,31 @@ ScriptPromise ContactsManager::select(ScriptState* script_state, ...@@ -113,22 +129,31 @@ ScriptPromise ContactsManager::select(ScriptState* script_state,
"Contacts Picker is already in use.")); "Contacts Picker is already in use."));
} }
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
bool include_names = false; bool include_names = false;
bool include_emails = false; bool include_emails = false;
bool include_tel = false; bool include_tel = false;
for (const String& property : properties) { for (const String& property : properties) {
if (property == "name") if (!base::Contains(properties_, property)) {
return ScriptPromise::Reject(
script_state,
V8ThrowException::CreateTypeError(
script_state->GetIsolate(),
"The provided value '" + property +
"' is not a valid enum value of type ContactProperty"));
}
if (property == kName)
include_names = true; include_names = true;
else if (property == "email") else if (property == kEmail)
include_emails = true; include_emails = true;
else if (property == "tel") else if (property == kTel)
include_tel = true; include_tel = true;
} }
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
contact_picker_in_use_ = true; contact_picker_in_use_ = true;
GetContactsManager(script_state) GetContactsManager(script_state)
->Select(options->multiple(), include_names, include_emails, include_tel, ->Select(options->multiple(), include_names, include_emails, include_tel,
...@@ -166,4 +191,8 @@ void ContactsManager::OnContactsSelected( ...@@ -166,4 +191,8 @@ void ContactsManager::OnContactsSelected(
resolver->Resolve(contacts_list); resolver->Resolve(contacts_list);
} }
ScriptPromise ContactsManager::getProperties(ScriptState* script_state) {
return ScriptPromise::Cast(script_state, ToV8(properties_, script_state));
}
} // namespace blink } // namespace blink
...@@ -30,6 +30,7 @@ class ContactsManager final : public ScriptWrappable { ...@@ -30,6 +30,7 @@ class ContactsManager final : public ScriptWrappable {
ScriptPromise select(ScriptState* script_state, ScriptPromise select(ScriptState* script_state,
const Vector<String>& properties, const Vector<String>& properties,
ContactsSelectOptions* options); ContactsSelectOptions* options);
ScriptPromise getProperties(ScriptState* script_state);
private: private:
mojo::Remote<mojom::blink::ContactsManager>& GetContactsManager( mojo::Remote<mojom::blink::ContactsManager>& GetContactsManager(
...@@ -42,6 +43,7 @@ class ContactsManager final : public ScriptWrappable { ...@@ -42,6 +43,7 @@ class ContactsManager final : public ScriptWrappable {
// Created lazily. // Created lazily.
mojo::Remote<mojom::blink::ContactsManager> contacts_manager_; mojo::Remote<mojom::blink::ContactsManager> contacts_manager_;
bool contact_picker_in_use_ = false; bool contact_picker_in_use_ = false;
Vector<String> properties_;
}; };
} // namespace blink } // namespace blink
......
...@@ -9,5 +9,6 @@ ...@@ -9,5 +9,6 @@
SecureContext, SecureContext,
RuntimeEnabled=ContactsManager RuntimeEnabled=ContactsManager
] interface ContactsManager { ] interface ContactsManager {
[CallWith=ScriptState, MeasureAs=ContactsManagerGetProperties] Promise<sequence<ContactProperty>> getProperties();
[CallWith=ScriptState, MeasureAs=ContactsManagerSelect] Promise<sequence<ContactInfo>> select(sequence<ContactProperty> properties, optional ContactsSelectOptions options); [CallWith=ScriptState, MeasureAs=ContactsManagerSelect] Promise<sequence<ContactInfo>> select(sequence<ContactProperty> properties, optional ContactsSelectOptions options);
}; };
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// https://wicg.github.io/contact-api/spec/#contacts-manager // https://wicg.github.io/contact-api/spec/#contacts-manager
enum ContactProperty { "email", "name", "tel" }; enum ContactProperty { "address", "email", "name", "tel" };
dictionary ContactsSelectOptions { dictionary ContactsSelectOptions {
boolean multiple = false; boolean multiple = false;
......
...@@ -320,6 +320,10 @@ ...@@ -320,6 +320,10 @@
origin_trial_os: ["android"], origin_trial_os: ["android"],
status: {"Android": "experimental", "default": "test"}, status: {"Android": "experimental", "default": "test"},
}, },
{
name: "ContactsManagerAddresses",
status: {"Android": "experimental", "default": "test"},
},
{ {
name: "ContentIndex", name: "ContentIndex",
status: "experimental", status: "experimental",
......
...@@ -47,6 +47,17 @@ contactsTestWithUserActivation(async (test, setSelectedContacts) => { ...@@ -47,6 +47,17 @@ contactsTestWithUserActivation(async (test, setSelectedContacts) => {
}, 'The Contact API can fail when the selector cannot be opened'); }, 'The Contact API can fail when the selector cannot be opened');
contactsTestWithUserActivation(async (test, setSelectedContacts) => {
setSelectedContacts([]);
const properties = await navigator.contacts.getProperties();
assert_true(properties.length > 0);
// Requesting the available properties should not fail.
await navigator.contacts.select(properties);
}, 'Supported contact properties are exposed.');
contactsTestWithUserActivation(async (test, setSelectedContacts) => { contactsTestWithUserActivation(async (test, setSelectedContacts) => {
// Returns two contacts with all information available. // Returns two contacts with all information available.
setSelectedContacts([ setSelectedContacts([
......
...@@ -1155,6 +1155,7 @@ interface ConstantSourceNode : AudioScheduledSourceNode ...@@ -1155,6 +1155,7 @@ interface ConstantSourceNode : AudioScheduledSourceNode
interface ContactsManager interface ContactsManager
attribute @@toStringTag attribute @@toStringTag
method constructor method constructor
method getProperties
method select method select
interface ContentIndex interface ContentIndex
attribute @@toStringTag attribute @@toStringTag
......
...@@ -24851,6 +24851,7 @@ Called by update_net_error_codes.py.--> ...@@ -24851,6 +24851,7 @@ Called by update_net_error_codes.py.-->
<int value="3041" label="FragmentHasTildeAtTilde"/> <int value="3041" label="FragmentHasTildeAtTilde"/>
<int value="3042" label="FragmentHasAmpersandDelimiterQuestion"/> <int value="3042" label="FragmentHasAmpersandDelimiterQuestion"/>
<int value="3043" label="InvalidFragmentDirective"/> <int value="3043" label="InvalidFragmentDirective"/>
<int value="3044" label="ContactsManagerGetProperties"/>
</enum> </enum>
<enum name="FeaturePolicyAllowlistType"> <enum name="FeaturePolicyAllowlistType">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment