Commit 5676bf28 authored by derat@chromium.org's avatar derat@chromium.org

chromeos: Use protocol buffers for Contact class.

This was formerly a hand-rolled C++ class, but Satoru
pointed out that using protocol buffers would make
serialization to disk much simpler.

BUG=128805
TEST=compiles
TBR=ben@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10830052

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148868 0039d316-1c4b-4281-b951-d872f2087c98
parent 11faec11
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/contacts/contact.h"
namespace contacts {
Contact::AddressType::AddressType() : relation(RELATION_OTHER) {}
Contact::EmailAddress::EmailAddress() : primary(false) {}
Contact::PhoneNumber::PhoneNumber() : primary(false) {}
Contact::PostalAddress::PostalAddress() : primary(false) {}
Contact::InstantMessagingAddress::InstantMessagingAddress()
: protocol(PROTOCOL_OTHER),
primary(false) {}
Contact::Contact() : deleted(false) {}
Contact::~Contact() {}
} // namespace contacts
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_CONTACTS_CONTACT_H_
#define CHROME_BROWSER_CHROMEOS_CONTACTS_CONTACT_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace contacts {
// Struct representing a contact, roughly based on the GData Contact kind:
// https://developers.google.com/gdata/docs/2.0/elements#gdContactKind
// All strings are UTF-8.
struct Contact {
// Describes an address-like field's type.
struct AddressType {
enum Relation {
RELATION_HOME = 0,
RELATION_WORK = 1,
RELATION_MOBILE = 2,
RELATION_OTHER = 3,
};
AddressType();
Relation relation;
std::string label;
};
struct EmailAddress {
EmailAddress();
std::string address;
AddressType type;
bool primary;
};
struct PhoneNumber {
PhoneNumber();
std::string number;
AddressType type;
bool primary;
};
struct PostalAddress {
PostalAddress();
std::string address;
AddressType type;
bool primary;
};
struct InstantMessagingAddress {
// Taken from https://developers.google.com/gdata/docs/2.0/elements#gdIm.
enum Protocol {
PROTOCOL_AIM = 0,
PROTOCOL_MSN = 1,
PROTOCOL_YAHOO = 2,
PROTOCOL_SKYPE = 3,
PROTOCOL_QQ = 4,
PROTOCOL_GOOGLE_TALK = 5,
PROTOCOL_ICQ = 6,
PROTOCOL_JABBER = 7,
PROTOCOL_OTHER = 8,
};
InstantMessagingAddress();
std::string address;
Protocol protocol;
AddressType type;
bool primary;
};
Contact();
~Contact();
int64 serialized_update_time() const {
return update_time.ToInternalValue();
}
void set_serialized_update_time(int64 serialized) {
update_time = base::Time::FromInternalValue(serialized);
}
// NOTE: Any changes to the below fields must be reflected in
// contact_test_util.cc's CopyContact() function.
// Provider-assigned unique identifier.
std::string provider_id;
// Last time at which this contact was updated.
base::Time update_time;
// Has the contact been deleted?
bool deleted;
// Taken from https://developers.google.com/gdata/docs/2.0/elements#gdName.
std::string full_name;
std::string given_name;
std::string additional_name;
std::string family_name;
std::string name_prefix;
std::string name_suffix;
SkBitmap photo;
std::vector<EmailAddress> email_addresses;
std::vector<PhoneNumber> phone_numbers;
std::vector<PostalAddress> postal_addresses;
std::vector<InstantMessagingAddress> instant_messaging_addresses;
DISALLOW_COPY_AND_ASSIGN(Contact);
};
typedef std::vector<const Contact*> ContactPointers;
} // namespace contacts
#endif // CHROME_BROWSER_CHROMEOS_CONTACTS_CONTACT_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Protocol buffer definitions for the user's contacts.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package contacts;
// A contact, roughly based on the GData Contact kind:
// https://developers.google.com/gdata/docs/2.0/elements#gdContactKind
// All strings are UTF-8.
message Contact {
// Next ID to use: 15
// Provider-assigned unique identifier.
optional string provider_id = 1;
// Last time at which this contact was updated within the upstream provider.
optional int64 update_time = 2;
// Has the contact been deleted recently within the upstream provider?
optional bool deleted = 3 [default = false];
// Taken from https://developers.google.com/gdata/docs/2.0/elements#gdName.
optional string full_name = 4;
optional string given_name = 5;
optional string additional_name = 6;
optional string family_name = 7;
optional string name_prefix = 8;
optional string name_suffix = 9;
// Raw photo data as supplied by the provider. This data is untrusted and
// must be decoded within a sandbox by e.g. ImageDecoder before being used.
// Unset if no photo is available.
optional bytes raw_untrusted_photo = 10;
// Describes an address-like message's type.
message AddressType {
// Next ID to use: 3
enum Relation {
HOME = 0;
WORK = 1;
MOBILE = 2;
OTHER = 3;
}
optional Relation relation = 1 [default = OTHER];
optional string label = 2;
}
message EmailAddress {
// Next ID to use: 4
optional string address = 1;
optional AddressType type = 2;
optional bool primary = 3 [default = false];
}
repeated EmailAddress email_addresses = 11;
message PhoneNumber {
// Next ID to use: 4
optional string number = 1;
optional AddressType type = 2;
optional bool primary = 3 [default = false];
}
repeated PhoneNumber phone_numbers = 12;
message PostalAddress {
// Next ID to use: 4
optional string address = 1;
optional AddressType type = 2;
optional bool primary = 3 [default = false];
}
repeated PostalAddress postal_addresses = 13;
message InstantMessagingAddress {
// Next ID to use: 5
optional string address = 1;
// Taken from https://developers.google.com/gdata/docs/2.0/elements#gdIm.
enum Protocol {
AIM = 0;
MSN = 1;
YAHOO = 2;
SKYPE = 3;
QQ = 4;
GOOGLE_TALK = 5;
ICQ = 6;
JABBER = 7;
OTHER = 8;
}
optional Protocol protocol = 2 [default = OTHER];
optional AddressType type = 3;
optional bool primary = 4 [default = false];
}
repeated InstantMessagingAddress instant_messaging_addresses = 14;
}
......@@ -13,6 +13,7 @@
#include "base/string_util.h"
#include "base/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size.h"
namespace contacts {
......@@ -24,73 +25,83 @@ namespace {
// and then sorts the resulting strings and joins them using |join_char|.
template<class T>
std::string StringifyField(
const std::vector<T>& items,
const ::google::protobuf::RepeatedPtrField<T>& items,
base::Callback<std::string(const T&)> stringify_callback,
const std::string& prefix,
char join_char) {
std::vector<std::string> strings;
for (size_t i = 0; i < items.size(); ++i)
strings.push_back(prefix + stringify_callback.Run(items[i]));
for (int i = 0; i < items.size(); ++i)
strings.push_back(prefix + stringify_callback.Run(items.Get(i)));
std::sort(strings.begin(), strings.end());
return JoinString(strings, join_char);
}
std::string EmailAddressToString(const Contact::EmailAddress& email) {
return email.address + "," +
base::IntToString(email.type.relation) + "," +
email.type.label + "," +
base::IntToString(email.primary);
std::string EmailAddressToString(const Contact_EmailAddress& email) {
return email.address() + "," +
base::IntToString(email.type().relation()) + "," +
email.type().label() + "," +
base::IntToString(email.primary());
}
std::string PhoneNumberToString(const Contact::PhoneNumber& phone) {
return phone.number + "," +
base::IntToString(phone.type.relation) + "," +
phone.type.label + "," +
base::IntToString(phone.primary);
std::string PhoneNumberToString(const Contact_PhoneNumber& phone) {
return phone.number() + "," +
base::IntToString(phone.type().relation()) + "," +
phone.type().label() + "," +
base::IntToString(phone.primary());
}
std::string PostalAddressToString(const Contact::PostalAddress& postal) {
return postal.address + "," +
base::IntToString(postal.type.relation) + "," +
postal.type.label + "," +
base::IntToString(postal.primary);
std::string PostalAddressToString(const Contact_PostalAddress& postal) {
return postal.address() + "," +
base::IntToString(postal.type().relation()) + "," +
postal.type().label() + "," +
base::IntToString(postal.primary());
}
std::string InstantMessagingAddressToString(
const Contact::InstantMessagingAddress& im) {
return im.address + "," +
base::IntToString(im.protocol) + "," +
base::IntToString(im.type.relation) + "," +
im.type.label + "," +
base::IntToString(im.primary);
const Contact_InstantMessagingAddress& im) {
return im.address() + "," +
base::IntToString(im.protocol()) + "," +
base::IntToString(im.type().relation()) + "," +
im.type().label() + "," +
base::IntToString(im.primary());
}
} // namespace
std::string ContactToString(const Contact& contact) {
std::string result =
contact.provider_id + "," +
base::Int64ToString(contact.update_time.ToInternalValue()) + "," +
base::IntToString(contact.deleted) + "," +
contact.full_name + "," +
contact.given_name + "," +
contact.additional_name + "," +
contact.family_name + "," +
contact.name_prefix + "," +
contact.name_suffix + "," +
base::IntToString(contact.photo.width()) + "x" +
base::IntToString(contact.photo.height());
result += " " + StringifyField(contact.email_addresses,
contact.provider_id() + "," +
base::Int64ToString(contact.update_time()) + "," +
base::IntToString(contact.deleted()) + "," +
contact.full_name() + "," +
contact.given_name() + "," +
contact.additional_name() + "," +
contact.family_name() + "," +
contact.name_prefix() + "," +
contact.name_suffix();
SkBitmap bitmap;
if (contact.has_raw_untrusted_photo()) {
// Testing code just uses PNG for now. If that changes, use ImageDecoder
// here instead.
CHECK(gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(
contact.raw_untrusted_photo().data()),
contact.raw_untrusted_photo().size(),
&bitmap));
}
result += "," + base::IntToString(bitmap.width()) + "x" +
base::IntToString(bitmap.height());
result += " " + StringifyField(contact.email_addresses(),
base::Bind(EmailAddressToString),
"email=", ' ');
result += " " + StringifyField(contact.phone_numbers,
result += " " + StringifyField(contact.phone_numbers(),
base::Bind(PhoneNumberToString),
"phone=", ' ');
result += " " + StringifyField(contact.postal_addresses,
result += " " + StringifyField(contact.postal_addresses(),
base::Bind(PostalAddressToString),
"postal=", ' ');
result += " " + StringifyField(contact.instant_messaging_addresses,
result += " " + StringifyField(contact.instant_messaging_addresses(),
base::Bind(InstantMessagingAddressToString),
"im=", ' ');
......@@ -122,30 +133,13 @@ std::string VarContactsToString(int num_contacts, ...) {
return ContactsToString(contacts);
}
void CopyContact(const Contact& source, Contact* dest) {
dest->provider_id = source.provider_id;
dest->update_time = source.update_time;
dest->deleted = source.deleted;
dest->full_name = source.full_name;
dest->given_name = source.given_name;
dest->additional_name = source.additional_name;
dest->family_name = source.family_name;
dest->name_prefix = source.name_prefix;
dest->name_suffix = source.name_suffix;
dest->photo = source.photo;
dest->email_addresses = source.email_addresses;
dest->phone_numbers = source.phone_numbers;
dest->postal_addresses = source.postal_addresses;
dest->instant_messaging_addresses = source.instant_messaging_addresses;
}
void CopyContacts(const ContactPointers& source,
ScopedVector<Contact>* dest) {
DCHECK(dest);
dest->clear();
for (size_t i = 0; i < source.size(); ++i) {
Contact* contact = new Contact;
CopyContact(*source[i], contact);
*contact = *source[i];
dest->push_back(contact);
}
}
......@@ -163,86 +157,86 @@ void InitContact(const std::string& provider_id,
bool deleted,
Contact* contact) {
DCHECK(contact);
contact->provider_id = provider_id;
contact->update_time = base::Time::Now();
contact->deleted = deleted;
contact->full_name = "full_name_" + name_suffix;
contact->given_name = "given_name_" + name_suffix;
contact->additional_name = "additional_name_" + name_suffix;
contact->family_name = "family_name_" + name_suffix;
contact->name_prefix = "name_prefix_" + name_suffix;
contact->name_suffix = "name_suffix_" + name_suffix;
contact->photo = SkBitmap();
contact->email_addresses.clear();
contact->phone_numbers.clear();
contact->postal_addresses.clear();
contact->instant_messaging_addresses.clear();
contact->Clear();
contact->set_provider_id(provider_id);
contact->set_update_time(base::Time::Now().ToInternalValue());
contact->set_deleted(deleted);
contact->set_full_name("full_name_" + name_suffix);
contact->set_given_name("given_name_" + name_suffix);
contact->set_additional_name("additional_name_" + name_suffix);
contact->set_family_name("family_name_" + name_suffix);
contact->set_name_prefix("name_prefix_" + name_suffix);
contact->set_name_suffix("name_suffix_" + name_suffix);
}
void AddEmailAddress(const std::string& address,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact) {
DCHECK(contact);
Contact::EmailAddress email;
email.address = address;
email.type.relation = relation;
email.type.label = label;
email.primary = primary;
contact->email_addresses.push_back(email);
Contact::EmailAddress* email = contact->add_email_addresses();
email->set_address(address);
email->mutable_type()->set_relation(relation);
email->mutable_type()->set_label(label);
email->set_primary(primary);
}
void AddPhoneNumber(const std::string& number,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact) {
DCHECK(contact);
Contact::PhoneNumber phone;
phone.number = number;
phone.type.relation = relation;
phone.type.label = label;
phone.primary = primary;
contact->phone_numbers.push_back(phone);
Contact::PhoneNumber* phone = contact->add_phone_numbers();
phone->set_number(number);
phone->mutable_type()->set_relation(relation);
phone->mutable_type()->set_label(label);
phone->set_primary(primary);
}
void AddPostalAddress(const std::string& address,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact) {
DCHECK(contact);
Contact::PostalAddress postal;
postal.address = address;
postal.type.relation = relation;
postal.type.label = label;
postal.primary = primary;
contact->postal_addresses.push_back(postal);
Contact::PostalAddress* postal = contact->add_postal_addresses();
postal->set_address(address);
postal->mutable_type()->set_relation(relation);
postal->mutable_type()->set_label(label);
postal->set_primary(primary);
}
void AddInstantMessagingAddress(
const std::string& address,
Contact::InstantMessagingAddress::Protocol protocol,
Contact::AddressType::Relation relation,
Contact_InstantMessagingAddress_Protocol protocol,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact) {
DCHECK(contact);
Contact::InstantMessagingAddress im;
im.address = address;
im.protocol = protocol;
im.type.relation = relation;
im.type.label = label;
im.primary = primary;
contact->instant_messaging_addresses.push_back(im);
Contact::InstantMessagingAddress* im =
contact->add_instant_messaging_addresses();
im->set_address(address);
im->set_protocol(protocol);
im->mutable_type()->set_relation(relation);
im->mutable_type()->set_label(label);
im->set_primary(primary);
}
void SetPhoto(const gfx::Size& size, Contact* contact) {
DCHECK(contact);
contact->photo.setConfig(
SkBitmap::kARGB_8888_Config, size.width(), size.height());
contact->photo.allocPixels();
if (size.IsEmpty()) {
contact->clear_raw_untrusted_photo();
return;
}
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
bitmap.allocPixels();
std::vector<unsigned char> png_photo;
CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_photo));
contact->set_raw_untrusted_photo(&png_photo[0], png_photo.size());
}
} // namespace test
......
......@@ -8,12 +8,14 @@
#include <string>
#include "base/memory/scoped_vector.h"
#include "chrome/browser/chromeos/contacts/contact.h"
#include "chrome/browser/chromeos/contacts/contact.pb.h"
#include "ui/gfx/size.h"
namespace contacts {
namespace test {
typedef std::vector<const Contact*> ContactPointers;
// Returns a string containing the information stored in |contact|. The same
// string will be returned for functionally-equivalent contacts (e.g. ones
// containing the same email addresses but in a different order).
......@@ -28,9 +30,6 @@ std::string ContactsToString(const ScopedVector<Contact>& contacts);
// const Contact* arguments.
std::string VarContactsToString(int num_contacts, ...);
// Copies |source|'s data to |dest|.
void CopyContact(const Contact& source, Contact* dest);
// Saves copies of all contacts in |source| to |dest|.
void CopyContacts(const ContactPointers& source,
ScopedVector<Contact>* dest);
......@@ -49,21 +48,21 @@ void InitContact(const std::string& provider_id,
// Adds an email address to |contact|.
void AddEmailAddress(const std::string& address,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact);
// Adds a phone number to |contact|.
void AddPhoneNumber(const std::string& number,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact);
// Adds a postal address to |contact|.
void AddPostalAddress(const std::string& address,
Contact::AddressType::Relation relation,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact);
......@@ -71,8 +70,8 @@ void AddPostalAddress(const std::string& address,
// Adds an IM address to |contact|.
void AddInstantMessagingAddress(
const std::string& address,
Contact::InstantMessagingAddress::Protocol protocol,
Contact::AddressType::Relation relation,
Contact_InstantMessagingAddress_Protocol protocol,
Contact_AddressType_Relation relation,
const std::string& label,
bool primary,
Contact* contact);
......
......@@ -30,6 +30,7 @@
'safe_browsing_report_proto',
'feedback_proto',
'gdata_proto',
'contacts_proto',
'variations_seed_proto',
'../build/temp_gyp/googleurl.gyp:googleurl',
'../content/content.gyp:content_browser',
......@@ -451,8 +452,6 @@
'browser/chromeos/choose_mobile_network_dialog.h',
'browser/chromeos/chrome_browser_main_chromeos.cc',
'browser/chromeos/chrome_browser_main_chromeos.h',
'browser/chromeos/contacts/contact.cc',
'browser/chromeos/contacts/contact.h',
'browser/chromeos/cros/burn_library.cc',
'browser/chromeos/cros/burn_library.h',
'browser/chromeos/cros/cellular_data_plan.cc',
......@@ -5446,6 +5445,17 @@
},
'includes': [ '../build/protoc.gypi' ]
},
{
# Protobuf compiler / generator for contacts-related protocol buffers.
'target_name': 'contacts_proto',
'type': 'static_library',
'sources': [ 'browser/chromeos/contacts/contact.proto' ],
'variables': {
'proto_in_dir': 'browser/chromeos/contacts',
'proto_out_dir': 'chrome/browser/chromeos/contacts',
},
'includes': [ '../build/protoc.gypi' ]
},
{
# Protobuf compiler / generator for Chrome Variations seed.
'target_name': 'variations_seed_proto',
......
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