#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/glue/typed_url_model_associator.h"
#include "chrome/browser/sync/profile_sync_service.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "sync/internal_api/public/change_record.h"
#include "sync/internal_api/public/read_node.h"
Profile* profile,
TypedUrlModelAssociator* model_associator,
history::HistoryBackend* history_backend,
- DataTypeErrorHandler* error_handler)
- : ChangeProcessor(error_handler),
+ sync_driver::DataTypeErrorHandler* error_handler)
+ : sync_driver::ChangeProcessor(error_handler),
profile_(profile),
model_associator_(model_associator),
history_backend_(history_backend),
TypedUrlChangeProcessor::~TypedUrlChangeProcessor() {
DCHECK(backend_loop_ == base::MessageLoop::current());
+ DCHECK(history_backend_);
+ history_backend_->RemoveObserver(this);
}
void TypedUrlChangeProcessor::Observe(
} else if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) {
HandleURLsDeleted(
content::Details<history::URLsDeletedDetails>(details).ptr());
- } else {
- DCHECK_EQ(chrome::NOTIFICATION_HISTORY_URL_VISITED, type);
- HandleURLsVisited(
- content::Details<history::URLVisitedDetails>(details).ptr());
+ }
+ UMA_HISTOGRAM_PERCENTAGE("Sync.TypedUrlChangeProcessorErrors",
+ model_associator_->GetErrorPercentage());
+}
+
+void TypedUrlChangeProcessor::OnURLVisited(
+ history::HistoryBackend* history_backend,
+ ui::PageTransition transition,
+ const history::URLRow& row,
+ const history::RedirectList& redirects,
+ base::Time visit_time) {
+ DCHECK(backend_loop_ == base::MessageLoop::current());
+
+ base::AutoLock al(disconnect_lock_);
+ if (disconnected_)
+ return;
+
+ DVLOG(1) << "Observed typed_url change.";
+ if (ShouldSyncVisit(row.typed_count(), transition)) {
+ syncer::WriteTransaction trans(FROM_HERE, share_handle());
+ CreateOrUpdateSyncNode(row, &trans);
}
UMA_HISTOGRAM_PERCENTAGE("Sync.TypedUrlChangeProcessorErrors",
model_associator_->GetErrorPercentage());
}
syncer::ReadNode typed_url_root(trans);
- if (typed_url_root.InitByTagLookup(kTypedUrlTag) !=
+ if (typed_url_root.InitTypeRoot(syncer::TYPED_URLS) !=
syncer::BaseNode::INIT_OK) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Server did not create the top-level typed_url node. We "
- "might be running against an out-of-date server.");
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "No top level folder",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
return false;
}
if (result == syncer::BaseNode::INIT_OK) {
model_associator_->WriteToSyncNode(url, visit_vector, &update_node);
} else if (result == syncer::BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY) {
- // TODO(tim): Investigating bug 121587.
- syncer::Cryptographer* crypto = trans->GetCryptographer();
- syncer::ModelTypeSet encrypted_types(trans->GetEncryptedTypes());
- const sync_pb::EntitySpecifics& specifics =
- update_node.GetEntry()->GetSpecifics();
- CHECK(specifics.has_encrypted());
- const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted());
- const bool agreement = encrypted_types.Has(syncer::TYPED_URLS);
- if (!agreement && !can_decrypt) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Could not InitByIdLookup in CreateOrUpdateSyncNode, "
- " Cryptographer thinks typed urls not encrypted, and CanDecrypt"
- " failed.");
- LOG(ERROR) << "Case 1.";
- } else if (agreement && can_decrypt) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Could not InitByIdLookup on CreateOrUpdateSyncNode, "
- " Cryptographer thinks typed urls are encrypted, and CanDecrypt"
- " succeeded (?!), but DecryptIfNecessary failed.");
- LOG(ERROR) << "Case 2.";
- } else if (agreement) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Could not InitByIdLookup on CreateOrUpdateSyncNode, "
- " Cryptographer thinks typed urls are encrypted, but CanDecrypt"
- " failed.");
- LOG(ERROR) << "Case 3.";
- } else {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Could not InitByIdLookup on CreateOrUpdateSyncNode, "
- " Cryptographer thinks typed urls not encrypted, but CanDecrypt"
- " succeeded (super weird, btw)");
- LOG(ERROR) << "Case 4.";
- }
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed to decrypt.",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
+ return false;
} else {
syncer::WriteNode create_node(trans);
syncer::WriteNode::InitUniqueByCreationResult result =
create_node.InitUniqueByCreation(syncer::TYPED_URLS,
typed_url_root, tag);
if (result != syncer::WriteNode::INIT_SUCCESS) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "Failed to create typed_url sync node.");
+
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed to create sync node",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
return false;
}
- create_node.SetTitle(UTF8ToWide(tag));
+ create_node.SetTitle(tag);
model_associator_->WriteToSyncNode(url, visit_vector, &create_node);
}
return true;
// a bad clock setting won't go on an archival rampage and delete all
// history from every client). The server will gracefully age out the sync DB
// entries when they've been idle for long enough.
- if (details->archived)
+ if (details->expired)
return;
if (details->all_history) {
if (!model_associator_->DeleteAllNodes(&trans)) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- std::string());
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed to delete local nodes.",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
return;
}
} else {
}
}
-void TypedUrlChangeProcessor::HandleURLsVisited(
- history::URLVisitedDetails* details) {
- if (!ShouldSyncVisit(details))
- return;
-
- syncer::WriteTransaction trans(FROM_HERE, share_handle());
- CreateOrUpdateSyncNode(details->row, &trans);
-}
-
-bool TypedUrlChangeProcessor::ShouldSyncVisit(
- history::URLVisitedDetails* details) {
- int typed_count = details->row.typed_count();
- content::PageTransition transition = static_cast<content::PageTransition>(
- details->transition & content::PAGE_TRANSITION_CORE_MASK);
-
+bool TypedUrlChangeProcessor::ShouldSyncVisit(int typed_count,
+ ui::PageTransition transition) {
// Just use an ad-hoc criteria to determine whether to ignore this
// notification. For most users, the distribution of visits is roughly a bell
// curve with a long tail - there are lots of URLs with < 5 visits so we want
// suggestions. But there are relatively few URLs with > 10 visits, and those
// tend to be more broadly distributed such that there's no need to sync up
// every visit to preserve their relative ordering.
- return (transition == content::PAGE_TRANSITION_TYPED &&
+ return (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
typed_count > 0 &&
(typed_count < kTypedUrlVisitThrottleThreshold ||
(typed_count % kTypedUrlVisitThrottleMultiple) == 0));
return;
syncer::ReadNode typed_url_root(trans);
- if (typed_url_root.InitByTagLookup(kTypedUrlTag) !=
+ if (typed_url_root.InitTypeRoot(syncer::TYPED_URLS) !=
syncer::BaseNode::INIT_OK) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "TypedUrl root node lookup failed.");
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed to init type root.",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
return;
}
syncer::ReadNode sync_node(trans);
if (sync_node.InitByIdLookup(it->id) != syncer::BaseNode::INIT_OK) {
- error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
- "TypedUrl node lookup failed.");
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed to init sync node.",
+ syncer::TYPED_URLS);
+ error_handler()->OnSingleDataTypeUnrecoverableError(error);
return;
}
disconnected_ = true;
}
-void TypedUrlChangeProcessor::StartImpl(Profile* profile) {
+void TypedUrlChangeProcessor::StartImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(profile, profile_);
DCHECK(history_backend_);
DCHECK(backend_loop_);
backend_loop_->PostTask(FROM_HERE,
void TypedUrlChangeProcessor::StartObserving() {
DCHECK(backend_loop_ == base::MessageLoop::current());
+ DCHECK(history_backend_);
DCHECK(profile_);
notification_registrar_.Add(
this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
notification_registrar_.Add(
this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::Source<Profile>(profile_));
- notification_registrar_.Add(
- this, chrome::NOTIFICATION_HISTORY_URL_VISITED,
- content::Source<Profile>(profile_));
+ history_backend_->AddObserver(this);
}
void TypedUrlChangeProcessor::StopObserving() {
DCHECK(backend_loop_ == base::MessageLoop::current());
+ DCHECK(history_backend_);
DCHECK(profile_);
notification_registrar_.Remove(
this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
notification_registrar_.Remove(
this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::Source<Profile>(profile_));
- notification_registrar_.Remove(
- this, chrome::NOTIFICATION_HISTORY_URL_VISITED,
- content::Source<Profile>(profile_));
+ history_backend_->RemoveObserver(this);
}
} // namespace browser_sync