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 {
kFragmentHasTildeAtTilde = 3041,
kFragmentHasAmpersandDelimiterQuestion = 3042,
kInvalidFragmentDirective = 3043,
kContactsManagerGetProperties = 3044,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
......
......@@ -4,6 +4,7 @@
#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/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
......@@ -64,8 +65,23 @@ TypeConverter<blink::ContactInfo*, blink::mojom::blink::ContactInfoPtr>::
} // namespace mojo
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;
mojo::Remote<mojom::blink::ContactsManager>&
......@@ -113,22 +129,31 @@ ScriptPromise ContactsManager::select(ScriptState* script_state,
"Contacts Picker is already in use."));
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
bool include_names = false;
bool include_emails = false;
bool include_tel = false;
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;
else if (property == "email")
else if (property == kEmail)
include_emails = true;
else if (property == "tel")
else if (property == kTel)
include_tel = true;
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
contact_picker_in_use_ = true;
GetContactsManager(script_state)
->Select(options->multiple(), include_names, include_emails, include_tel,
......@@ -166,4 +191,8 @@ void ContactsManager::OnContactsSelected(
resolver->Resolve(contacts_list);
}
ScriptPromise ContactsManager::getProperties(ScriptState* script_state) {
return ScriptPromise::Cast(script_state, ToV8(properties_, script_state));
}
} // namespace blink
......@@ -30,6 +30,7 @@ class ContactsManager final : public ScriptWrappable {
ScriptPromise select(ScriptState* script_state,
const Vector<String>& properties,
ContactsSelectOptions* options);
ScriptPromise getProperties(ScriptState* script_state);
private:
mojo::Remote<mojom::blink::ContactsManager>& GetContactsManager(
......@@ -42,6 +43,7 @@ class ContactsManager final : public ScriptWrappable {
// Created lazily.
mojo::Remote<mojom::blink::ContactsManager> contacts_manager_;
bool contact_picker_in_use_ = false;
Vector<String> properties_;
};
} // namespace blink
......
......@@ -9,5 +9,6 @@
SecureContext,
RuntimeEnabled=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);
};
......@@ -4,7 +4,7 @@
// https://wicg.github.io/contact-api/spec/#contacts-manager
enum ContactProperty { "email", "name", "tel" };
enum ContactProperty { "address", "email", "name", "tel" };
dictionary ContactsSelectOptions {
boolean multiple = false;
......
......@@ -320,6 +320,10 @@
origin_trial_os: ["android"],
status: {"Android": "experimental", "default": "test"},
},
{
name: "ContactsManagerAddresses",
status: {"Android": "experimental", "default": "test"},
},
{
name: "ContentIndex",
status: "experimental",
......
......@@ -47,6 +47,17 @@ contactsTestWithUserActivation(async (test, setSelectedContacts) => {
}, '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) => {
// Returns two contacts with all information available.
setSelectedContacts([
......
......@@ -1155,6 +1155,7 @@ interface ConstantSourceNode : AudioScheduledSourceNode
interface ContactsManager
attribute @@toStringTag
method constructor
method getProperties
method select
interface ContentIndex
attribute @@toStringTag
......
......@@ -24851,6 +24851,7 @@ Called by update_net_error_codes.py.-->
<int value="3041" label="FragmentHasTildeAtTilde"/>
<int value="3042" label="FragmentHasAmpersandDelimiterQuestion"/>
<int value="3043" label="InvalidFragmentDirective"/>
<int value="3044" label="ContactsManagerGetProperties"/>
</enum>
<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