Chromium Code Reviews| Index: chrome/browser/sync/engine/syncapi.cc |
| diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc |
| index 37f56ab32b354d687300b1c301fdda31de41a394..5b3ba21b6e078aebd92299f2814edc63cf204023 100644 |
| --- a/chrome/browser/sync/engine/syncapi.cc |
| +++ b/chrome/browser/sync/engine/syncapi.cc |
| @@ -8,11 +8,14 @@ |
| #include <bitset> |
| #include <iomanip> |
| #include <list> |
| +#include <map> |
| #include <queue> |
| #include <string> |
| #include <vector> |
| #include "base/base64.h" |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| #include "base/command_line.h" |
| #include "base/json/json_writer.h" |
| #include "base/logging.h" |
| @@ -330,17 +333,22 @@ int64 BaseNode::GetFirstChildId() const { |
| return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); |
| } |
| -DictionaryValue* BaseNode::ToValue() const { |
| +DictionaryValue* BaseNode::GetSummaryAsValue() const { |
| DictionaryValue* node_info = new DictionaryValue(); |
| node_info->SetString("id", base::Int64ToString(GetId())); |
| - // TODO(akalin): Return time in a better format. |
| - node_info->SetString("modificationTime", |
| - base::Int64ToString(GetModificationTime())); |
| - node_info->SetString("parentId", base::Int64ToString(GetParentId())); |
| node_info->SetBoolean("isFolder", GetIsFolder()); |
| // TODO(akalin): Add a std::string accessor for the title. |
| node_info->SetString("title", WideToUTF8(GetTitle())); |
| node_info->Set("type", ModelTypeToValue(GetModelType())); |
| + return node_info; |
| +} |
| + |
| +DictionaryValue* BaseNode::GetDetailsAsValue() const { |
| + DictionaryValue* node_info = GetSummaryAsValue(); |
| + // TODO(akalin): Return time in a better format. |
| + node_info->SetString("modificationTime", |
| + base::Int64ToString(GetModificationTime())); |
| + node_info->SetString("parentId", base::Int64ToString(GetParentId())); |
| // Specifics are already in the Entry value, so no need to duplicate |
| // it here. |
| node_info->SetString("externalId", |
| @@ -1101,7 +1109,7 @@ DictionaryValue* SyncManager::ChangeRecord::ToValue( |
| } else { |
| ReadNode node(trans); |
| if (node.InitByIdLookup(id)) { |
| - node_value = node.ToValue(); |
| + node_value = node.GetDetailsAsValue(); |
| } |
| } |
| if (!node_value) { |
| @@ -1112,34 +1120,6 @@ DictionaryValue* SyncManager::ChangeRecord::ToValue( |
| return value; |
| } |
| -bool BaseNode::ContainsString(const std::string& lowercase_query) const { |
| - DCHECK(GetEntry()); |
| - // TODO(lipalani) - figure out what to do if the node is encrypted. |
| - const sync_pb::EntitySpecifics& specifics = GetEntry()->Get(SPECIFICS); |
| - std::string temp; |
| - // The protobuf serialized string contains the original strings. So |
| - // we will just serialize it and search it. |
| - specifics.SerializeToString(&temp); |
| - |
| - // Now convert to lower case. |
| - StringToLowerASCII(&temp); |
| - |
| - if (temp.find(lowercase_query) != std::string::npos) |
| - return true; |
| - |
| - // Now go through all the string fields to see if the value is there. |
| - for (int i = syncable::STRING_FIELDS_BEGIN; i < syncable::STRING_FIELDS_END; |
| - ++i) { |
| - std::string value = GetEntry()->Get( |
| - static_cast<syncable::StringField>(i)); |
| - |
| - StringToLowerASCII(&value); |
| - if (value.find(lowercase_query) != std::string::npos) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} |
| SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( |
| @@ -1224,6 +1204,29 @@ class SyncManager::SyncInternal |
| notification_info_map_.insert( |
| std::make_pair(syncable::ModelTypeFromInt(i), NotificationInfo())); |
| } |
| + |
|
lipalani1
2011/06/02 23:06:39
This list does not seem to change. So is it possib
akalin
2011/06/02 23:14:58
As we discussed, C++ isn't expressive enough to do
|
| + // Bind message handlers. |
| + BindJsMessageHandler( |
| + "getNotificationState", |
| + &SyncManager::SyncInternal::GetNotificationState); |
| + BindJsMessageHandler( |
| + "getNotificationInfo", |
| + &SyncManager::SyncInternal::GetNotificationInfo); |
| + BindJsMessageHandler( |
| + "getRootNodeDetails", |
| + &SyncManager::SyncInternal::GetRootNodeDetails); |
| + BindJsMessageHandler( |
| + "getNodeSummariesById", |
| + &SyncManager::SyncInternal::GetNodeSummariesById); |
| + BindJsMessageHandler( |
| + "getNodeDetailsById", |
| + &SyncManager::SyncInternal::GetNodeDetailsById); |
| + BindJsMessageHandler( |
| + "getChildNodeIds", |
| + &SyncManager::SyncInternal::GetChildNodeIds); |
| + BindJsMessageHandler( |
| + "findNodesContainingString", |
| + &SyncManager::SyncInternal::FindNodesContainingString); |
| } |
| virtual ~SyncInternal() { |
| @@ -1442,9 +1445,14 @@ class SyncManager::SyncInternal |
| const browser_sync::JsArgList& args, |
| const browser_sync::JsEventHandler* target) OVERRIDE; |
| - ListValue* FindNodesContainingString(const std::string& query); |
| - |
| private: |
| + typedef browser_sync::JsArgList |
| + (SyncManager::SyncInternal::*UnboundJsMessageHandler)( |
| + const browser_sync::JsArgList&); |
| + typedef base::Callback<browser_sync::JsArgList(browser_sync::JsArgList)> |
| + JsMessageHandler; |
| + typedef std::map<std::string, JsMessageHandler> JsMessageHandlerMap; |
| + |
| // Helper to call OnAuthError when no authentication credentials are |
| // available. |
| void RaiseAuthNeededEvent(); |
| @@ -1556,14 +1564,31 @@ class SyncManager::SyncInternal |
| // Checks for server reachabilty and requests a nudge. |
| void OnIPAddressChangedImpl(); |
| - // Functions called by ProcessMessage(). |
| - browser_sync::JsArgList ProcessGetNodesByIdMessage( |
| + // Helper function used only by the constructor. |
| + void BindJsMessageHandler( |
| + const std::string& name, |
| + UnboundJsMessageHandler unbound_message_handler); |
| + |
| + // JS message handlers. |
| + browser_sync::JsArgList GetNotificationState( |
| const browser_sync::JsArgList& args); |
| - browser_sync::JsArgList ProcessGetChildNodeIdsMessage( |
| + browser_sync::JsArgList GetNotificationInfo( |
| const browser_sync::JsArgList& args); |
| - browser_sync::JsArgList ProcessFindNodesContainingString( |
| + browser_sync::JsArgList GetRootNodeDetails( |
| + const browser_sync::JsArgList& args); |
| + |
| + browser_sync::JsArgList GetNodeSummariesById( |
| + const browser_sync::JsArgList& args); |
| + |
| + browser_sync::JsArgList GetNodeDetailsById( |
| + const browser_sync::JsArgList& args); |
| + |
| + browser_sync::JsArgList GetChildNodeIds( |
| + const browser_sync::JsArgList& args); |
| + |
| + browser_sync::JsArgList FindNodesContainingString( |
| const browser_sync::JsArgList& args); |
| // We couple the DirectoryManager and username together in a UserShare member |
| @@ -1628,6 +1653,8 @@ class SyncManager::SyncInternal |
| NotificationInfoMap notification_info_map_; |
| browser_sync::JsDirectoryChangeListener js_directory_change_listener_; |
| + |
| + JsMessageHandlerMap js_message_handlers_; |
| }; |
| const int SyncManager::SyncInternal::kDefaultNudgeDelayMilliseconds = 200; |
| const int SyncManager::SyncInternal::kPreferencesNudgeDelayMilliseconds = 2000; |
| @@ -2126,52 +2153,6 @@ void SyncManager::SyncInternal::EncryptDataTypes( |
| return; |
| } |
| -namespace { |
| - |
| -void FindChildNodesContainingString(const std::string& lowercase_query, |
| - const ReadNode& parent_node, |
| - sync_api::ReadTransaction* trans, |
| - ListValue* result) { |
| - int64 child_id = parent_node.GetFirstChildId(); |
| - while (child_id != kInvalidId) { |
| - ReadNode node(trans); |
| - if (node.InitByIdLookup(child_id)) { |
| - if (node.ContainsString(lowercase_query)) { |
| - result->Append(new StringValue(base::Int64ToString(child_id))); |
| - } |
| - FindChildNodesContainingString(lowercase_query, node, trans, result); |
| - child_id = node.GetSuccessorId(); |
| - } else { |
| - LOG(WARNING) << "Lookup of node failed. Id: " << child_id; |
| - return; |
| - } |
| - } |
| -} |
| -} // namespace |
| - |
| -// Returned pointer owned by the caller. |
| -ListValue* SyncManager::SyncInternal::FindNodesContainingString( |
| - const std::string& query) { |
| - // Convert the query string to lower case to perform case insensitive |
| - // searches. |
| - std::string lowercase_query = query; |
| - StringToLowerASCII(&lowercase_query); |
| - ReadTransaction trans(GetUserShare()); |
| - ReadNode root(&trans); |
| - root.InitByRootLookup(); |
| - |
| - ListValue* result = new ListValue(); |
| - |
| - base::Time start_time = base::Time::Now(); |
| - FindChildNodesContainingString(lowercase_query, root, &trans, result); |
| - base::Time end_time = base::Time::Now(); |
| - |
| - base::TimeDelta delta = end_time - start_time; |
| - VLOG(1) << "Time taken in milliseconds to search " << delta.InMilliseconds(); |
| - |
| - return result; |
| -} |
| - |
| void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { |
| syncable::ModelTypeSet encrypted_types = |
| GetEncryptedDataTypes(trans->GetWrappedTrans()); |
| @@ -2685,77 +2666,25 @@ const browser_sync::JsEventRouter* |
| return parent_router_; |
| } |
| -namespace { |
| - |
| -void LogNoRouter(const std::string& name, |
| - const browser_sync::JsArgList& args) { |
| - VLOG(1) << "No parent router; not replying to message " << name |
| - << " with args " << args.ToString(); |
| -} |
| - |
| -} // namespace |
| - |
| void SyncManager::SyncInternal::ProcessMessage( |
| const std::string& name, const browser_sync::JsArgList& args, |
| const browser_sync::JsEventHandler* sender) { |
| DCHECK(initialized_); |
| - if (name == "getNotificationState") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| - bool notifications_enabled = allstatus_.status().notifications_enabled; |
| - ListValue return_args; |
| - return_args.Append(Value::CreateBooleanValue(notifications_enabled)); |
| - parent_router_->RouteJsMessageReply( |
| - name, browser_sync::JsArgList(&return_args), sender); |
| - } else if (name == "getNotificationInfo") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| + if (!parent_router_) { |
| + VLOG(1) << "No parent router; not replying to message " << name |
| + << " with args " << args.ToString(); |
| + return; |
| + } |
| - ListValue return_args; |
| - return_args.Append(NotificationInfoToValue(notification_info_map_)); |
| - parent_router_->RouteJsMessageReply( |
| - name, browser_sync::JsArgList(&return_args), sender); |
| - } else if (name == "getRootNode") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| - ReadTransaction trans(GetUserShare()); |
| - ReadNode root(&trans); |
| - root.InitByRootLookup(); |
| - ListValue return_args; |
| - return_args.Append(root.ToValue()); |
| - parent_router_->RouteJsMessageReply( |
| - name, browser_sync::JsArgList(&return_args), sender); |
| - } else if (name == "getNodesById") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| - parent_router_->RouteJsMessageReply( |
| - name, ProcessGetNodesByIdMessage(args), sender); |
| - } else if (name == "getChildNodeIds") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| - parent_router_->RouteJsMessageReply( |
| - name, ProcessGetChildNodeIdsMessage(args), sender); |
| - } else if (name == "findNodesContainingString") { |
| - if (!parent_router_) { |
| - LogNoRouter(name, args); |
| - return; |
| - } |
| - parent_router_->RouteJsMessageReply( |
| - name, ProcessFindNodesContainingString(args), sender); |
| - } else { |
| + JsMessageHandler js_message_handler = js_message_handlers_[name]; |
| + if (js_message_handler.is_null()) { |
| VLOG(1) << "Dropping unknown message " << name |
| << " with args " << args.ToString(); |
| + return; |
| } |
| + |
| + parent_router_->RouteJsMessageReply( |
| + name, js_message_handler.Run(args), sender); |
| } |
| void SyncManager::SyncInternal::RouteJsEvent( |
| @@ -2777,76 +2706,120 @@ void SyncManager::SyncInternal::RouteJsMessageReply( |
| parent_router_->RouteJsMessageReply(name, args, target); |
| } |
| +void SyncManager::SyncInternal::BindJsMessageHandler( |
| + const std::string& name, |
| + UnboundJsMessageHandler unbound_message_handler) { |
| + js_message_handlers_[name] = |
| + base::Bind(unbound_message_handler, base::Unretained(this)); |
| +} |
| + |
| +browser_sync::JsArgList |
| + SyncManager::SyncInternal::GetNotificationState( |
| + const browser_sync::JsArgList& args) { |
| + bool notifications_enabled = allstatus_.status().notifications_enabled; |
| + ListValue return_args; |
| + return_args.Append(Value::CreateBooleanValue(notifications_enabled)); |
| + return browser_sync::JsArgList(&return_args); |
| +} |
| + |
| +browser_sync::JsArgList |
| + SyncManager::SyncInternal::GetNotificationInfo( |
| + const browser_sync::JsArgList& args) { |
| + ListValue return_args; |
| + return_args.Append(NotificationInfoToValue(notification_info_map_)); |
| + return browser_sync::JsArgList(&return_args); |
| +} |
| + |
| +browser_sync::JsArgList |
| + SyncManager::SyncInternal::GetRootNodeDetails( |
| + const browser_sync::JsArgList& args) { |
| + ReadTransaction trans(GetUserShare()); |
| + ReadNode root(&trans); |
| + root.InitByRootLookup(); |
| + ListValue return_args; |
| + return_args.Append(root.GetDetailsAsValue()); |
| + return browser_sync::JsArgList(&return_args); |
| +} |
| + |
| namespace { |
| -bool GetId(const ListValue& ids, int i, int64* id) { |
| +int64 GetId(const ListValue& ids, int i) { |
| std::string id_str; |
| if (!ids.GetString(i, &id_str)) { |
| - return false; |
| - } |
| - if (!base::StringToInt64(id_str, id)) { |
| - return false; |
| + return kInvalidId; |
| } |
| - if (*id == kInvalidId) { |
| - return false; |
| + int64 id = kInvalidId; |
| + if (!base::StringToInt64(id_str, &id)) { |
| + return kInvalidId; |
| } |
| - return true; |
| + return id; |
| } |
| -} // namespace |
| - |
| -browser_sync::JsArgList SyncManager::SyncInternal::ProcessGetNodesByIdMessage( |
| - const browser_sync::JsArgList& args) { |
| +browser_sync::JsArgList GetNodeInfoById( |
| + const browser_sync::JsArgList& args, |
| + UserShare* user_share, |
| + DictionaryValue* (BaseNode::*info_getter)() const) { |
| + CHECK(info_getter); |
| ListValue return_args; |
| - ListValue* nodes = new ListValue(); |
| - return_args.Append(nodes); |
| + ListValue* node_summaries = new ListValue(); |
| + return_args.Append(node_summaries); |
| ListValue* id_list = NULL; |
| - ReadTransaction trans(GetUserShare()); |
| + ReadTransaction trans(user_share); |
| if (args.Get().GetList(0, &id_list)) { |
| + CHECK(id_list); |
| for (size_t i = 0; i < id_list->GetSize(); ++i) { |
| - int64 id = kInvalidId; |
| - if (!GetId(*id_list, i, &id)) { |
| + int64 id = GetId(*id_list, i); |
| + if (id == kInvalidId) { |
| continue; |
| } |
| ReadNode node(&trans); |
| if (!node.InitByIdLookup(id)) { |
| continue; |
| } |
| - nodes->Append(node.ToValue()); |
| + node_summaries->Append((node.*info_getter)()); |
| } |
| } |
| return browser_sync::JsArgList(&return_args); |
| } |
| +} // namespace |
| + |
| +browser_sync::JsArgList |
| + SyncManager::SyncInternal::GetNodeSummariesById( |
| + const browser_sync::JsArgList& args) { |
| + return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetSummaryAsValue); |
| +} |
| + |
| +browser_sync::JsArgList |
| + SyncManager::SyncInternal::GetNodeDetailsById( |
| + const browser_sync::JsArgList& args) { |
| + return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetDetailsAsValue); |
| +} |
| + |
| browser_sync::JsArgList SyncManager::SyncInternal:: |
| - ProcessGetChildNodeIdsMessage( |
| + GetChildNodeIds( |
| const browser_sync::JsArgList& args) { |
| ListValue return_args; |
| ListValue* child_ids = new ListValue(); |
| return_args.Append(child_ids); |
| - int64 id = kInvalidId; |
| - if (GetId(args.Get(), 0, &id)) { |
| + int64 id = GetId(args.Get(), 0); |
| + if (id != kInvalidId) { |
| ReadTransaction trans(GetUserShare()); |
| - ReadNode node(&trans); |
| - if (node.InitByIdLookup(id)) { |
| - int64 child_id = node.GetFirstChildId(); |
| - while (child_id != kInvalidId) { |
| - ReadNode child_node(&trans); |
| - if (!child_node.InitByIdLookup(child_id)) { |
| - break; |
| - } |
| - child_ids->Append(Value::CreateStringValue( |
| - base::Int64ToString(child_id))); |
| - child_id = child_node.GetSuccessorId(); |
| - } |
| + syncable::Directory::ChildHandles child_handles; |
| + trans.GetLookup()->GetChildHandlesByHandle(trans.GetWrappedTrans(), |
| + id, &child_handles); |
| + for (syncable::Directory::ChildHandles::const_iterator it = |
| + child_handles.begin(); it != child_handles.end(); ++it) { |
| + child_ids->Append(Value::CreateStringValue( |
| + base::Int64ToString(*it))); |
| } |
| } |
| return browser_sync::JsArgList(&return_args); |
| } |
| browser_sync::JsArgList SyncManager::SyncInternal:: |
| - ProcessFindNodesContainingString( |
| - const browser_sync::JsArgList& args) { |
| + FindNodesContainingString( |
| + const browser_sync::JsArgList& args) { |
| std::string query; |
| ListValue return_args; |
| if (!args.Get().GetString(0, &query)) { |
| @@ -2854,8 +2827,27 @@ browser_sync::JsArgList SyncManager::SyncInternal:: |
| return browser_sync::JsArgList(&return_args); |
| } |
| - ListValue* result = FindNodesContainingString(query); |
| + // Convert the query string to lower case to perform case insensitive |
| + // searches. |
| + std::string lowercase_query = query; |
| + StringToLowerASCII(&lowercase_query); |
| + |
| + ListValue* result = new ListValue(); |
| return_args.Append(result); |
| + |
| + ReadTransaction trans(GetUserShare()); |
| + std::vector<const syncable::EntryKernel*> entry_kernels; |
| + trans.GetLookup()->GetAllEntryKernels(trans.GetWrappedTrans(), |
| + &entry_kernels); |
| + |
| + for (std::vector<const syncable::EntryKernel*>::const_iterator it = |
| + entry_kernels.begin(); it != entry_kernels.end(); ++it) { |
| + if ((*it)->ContainsString(lowercase_query)) { |
| + result->Append(new StringValue(base::Int64ToString( |
| + (*it)->ref(syncable::META_HANDLE)))); |
| + } |
| + } |
| + |
| return browser_sync::JsArgList(&return_args); |
| } |
| @@ -3002,7 +2994,7 @@ void SyncManager::LogUnsyncedItems(int level) const { |
| it != unsynced_handles.end(); ++it) { |
| ReadNode node(&trans); |
| if (node.InitByIdLookup(*it)) { |
| - scoped_ptr<DictionaryValue> value(node.ToValue()); |
| + scoped_ptr<DictionaryValue> value(node.GetDetailsAsValue()); |
| std::string info; |
| base::JSONWriter::Write(value.get(), true, &info); |
| VLOG(level) << info; |