summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbradnelson@google.com <bradnelson@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-03 21:55:29 +0000
committerbradnelson@google.com <bradnelson@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-03 21:55:29 +0000
commit21e581224e3229921d1ffb955ead8cf826d7a009 (patch)
treed69d32705f75f50bbd38d6d57b0601f4c3eb751f /chrome
parent0ec65a206162e22de14d2c50661fee6046c0c877 (diff)
downloadchromium_src-21e581224e3229921d1ffb955ead8cf826d7a009.zip
chromium_src-21e581224e3229921d1ffb955ead8cf826d7a009.tar.gz
chromium_src-21e581224e3229921d1ffb955ead8cf826d7a009.tar.bz2
Rolling back 22317
BUG=None TEST=None TBR=tim Review URL: http://codereview.chromium.org/160542 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22321 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/sync/auth_error_state.h25
-rw-r--r--chrome/browser/sync/engine/syncapi.h709
-rw-r--r--chrome/browser/sync/glue/bookmark_model_worker.cc114
-rw-r--r--chrome/browser/sync/glue/bookmark_model_worker.h134
-rw-r--r--chrome/browser/sync/glue/bookmark_model_worker_unittest.cc224
-rw-r--r--chrome/browser/sync/glue/http_bridge.cc252
-rw-r--r--chrome/browser/sync/glue/http_bridge.h171
-rw-r--r--chrome/browser/sync/glue/http_bridge_unittest.cc167
-rw-r--r--chrome/browser/sync/glue/model_associator.cc504
-rw-r--r--chrome/browser/sync/glue/model_associator.h141
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc308
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h274
-rw-r--r--chrome/browser/sync/personalization.cc339
-rw-r--r--chrome/browser/sync/personalization.h111
-rw-r--r--chrome/browser/sync/personalization_strings.h69
-rw-r--r--chrome/browser/sync/profile_sync_service.cc886
-rw-r--r--chrome/browser/sync/profile_sync_service.h368
-rw-r--r--chrome/browser/sync/profile_sync_service_unittest.cc1272
-rw-r--r--chrome/browser/sync/resources/about_sync.html165
-rw-r--r--chrome/browser/sync/resources/close.pngbin178 -> 0 bytes
-rw-r--r--chrome/browser/sync/resources/gaia_login.html331
-rw-r--r--chrome/browser/sync/resources/gear.pngbin357 -> 0 bytes
-rw-r--r--chrome/browser/sync/resources/google_transparent.pngbin1580 -> 0 bytes
-rw-r--r--chrome/browser/sync/resources/merge_and_sync.html66
-rw-r--r--chrome/browser/sync/resources/merge_and_sync.pngbin7679 -> 0 bytes
-rw-r--r--chrome/browser/sync/resources/new_tab_personalization.html117
-rw-r--r--chrome/browser/sync/resources/setup_flow.html19
-rw-r--r--chrome/browser/sync/sync_status_ui_helper.cc101
-rw-r--r--chrome/browser/sync/sync_status_ui_helper.h34
29 files changed, 0 insertions, 6901 deletions
diff --git a/chrome/browser/sync/auth_error_state.h b/chrome/browser/sync/auth_error_state.h
deleted file mode 100644
index 863a9eb..0000000
--- a/chrome/browser/sync/auth_error_state.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2006-2008 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_PERSONALIZATION_AUTH_ERROR_STATE_H_
-#define CHROME_PERSONALIZATION_AUTH_ERROR_STATE_H_
-
-#include <string>
-#include "base/string_util.h"
-
-enum AuthErrorState {
- AUTH_ERROR_NONE = 0,
- // The credentials supplied to GAIA were either invalid, or the locally
- // cached credentials have expired. If this happens, the sync system
- // will continue as if offline until authentication is reattempted.
- AUTH_ERROR_INVALID_GAIA_CREDENTIALS,
- // The GAIA user is not authorized to use the sync service.
- AUTH_ERROR_USER_NOT_SIGNED_UP,
- // Could not connect to server to verify credentials. This could be in
- // response to either failure to connect to GAIA or failure to connect to
- // the service needing GAIA tokens during authentication.
- AUTH_ERROR_CONNECTION_FAILED,
-};
-
-#endif // CHROME_PERSONALIZATION_AUTH_ERROR_STATE
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
deleted file mode 100644
index da50cc2..0000000
--- a/chrome/browser/sync/engine/syncapi.h
+++ /dev/null
@@ -1,709 +0,0 @@
-// Copyright (c) 2009 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.
-
-// This file defines the "sync API", an interface to the syncer
-// backend that exposes (1) the core functionality of maintaining a consistent
-// local snapshot of a hierarchical object set; (2) a means to transactionally
-// access and modify those objects; (3) a means to control client/server
-// synchronization tasks, namely: pushing local object modifications to a
-// server, pulling nonlocal object modifications from a server to this client,
-// and resolving conflicts that may arise between the two; and (4) an
-// abstraction of some external functionality that is to be provided by the
-// host environment.
-//
-// This interface is used as the entry point into the syncer backend
-// when the backend is compiled as a library and embedded in another
-// application. A goal for this interface layer is to depend on very few
-// external types, so that an application can use the sync backend
-// without introducing a dependency on specific types. A non-goal is to
-// have binary compatibility across versions or compilers; this allows the
-// interface to use C++ classes. An application wishing to use the sync API
-// should ideally compile the syncer backend and this API as part of the
-// application's own build, to avoid e.g. mismatches in calling convention,
-// structure padding, or name mangling that could arise if there were a
-// compiler mismatch.
-//
-// The schema of the objects in the sync domain is based on the model, which
-// is essentially a hierarchy of items and folders similar to a filesystem,
-// but with a few important differences. The sync API contains fields
-// such as URL to easily allow the embedding application to store web
-// browser bookmarks. Also, the sync API allows duplicate titles in a parent.
-// Consequently, it does not support looking up an object by title
-// and parent, since such a lookup is not uniquely determined. Lastly,
-// unlike a filesystem model, objects in the Sync API model have a strict
-// ordering within a parent; the position is manipulable by callers, and
-// children of a node can be enumerated in the order of their position.
-
-#ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCAPI_H_
-#define CHROME_BROWSER_SYNC_ENGINE_SYNCAPI_H_
-
-#include "base/basictypes.h"
-
-#if (defined(OS_WIN) || defined(OS_WINDOWS))
-typedef wchar_t sync_char16;
-#else
-typedef uint16 sync_char16;
-#endif
-
-// The MSVC compiler for Windows requires that any classes exported by, or
-// imported from, a dynamic library be decorated with the following fanciness.
-#if (defined(OS_WIN) || defined(OS_WINDOWS))
-#if COMPILING_SYNCAPI_LIBRARY
-#define SYNC_EXPORT __declspec(dllexport)
-#else
-#define SYNC_EXPORT __declspec(dllimport)
-#endif
-#else
-#define SYNC_EXPORT
-#endif // OS_WIN || OS_WINDOWS
-
-// Forward declarations of internal class types so that sync API objects
-// may have opaque pointers to these types.
-namespace syncable {
-class BaseTransaction;
-class DirectoryManager;
-class Entry;
-class MutableEntry;
-class ReadTransaction;
-class ScopedDirLookup;
-class WriteTransaction;
-}
-
-namespace sync_api {
-
-// Forward declarations of classes to be defined later in this file.
-class BaseTransaction;
-class HttpPostProviderFactory;
-class ModelSafeWorkerInterface;
-class SyncManager;
-class WriteTransaction;
-struct UserShare;
-
-// A valid BaseNode will never have an ID of zero.
-static const int64 kInvalidId = 0;
-
-// BaseNode wraps syncable::Entry, and corresponds to a single object's state.
-// This, like syncable::Entry, is intended for use on the stack. A valid
-// transaction is necessary to create a BaseNode or any of its children.
-// Unlike syncable::Entry, a sync API BaseNode is identified primarily by its
-// int64 metahandle, which we call an ID here.
-class SYNC_EXPORT BaseNode {
- public:
- // All subclasses of BaseNode must provide a way to initialize themselves by
- // doing an ID lookup. Returns false on failure. An invalid or deleted
- // ID will result in failure.
- virtual bool InitByIdLookup(int64 id) = 0;
-
- // Each object is identified by a 64-bit id (internally, the syncable
- // metahandle). These ids are strictly local handles. They will persist
- // on this client, but the same object on a different client may have a
- // different ID value.
- int64 GetId() const;
-
- // Nodes are hierarchically arranged into a single-rooted tree.
- // InitByRootLookup on ReadNode allows access to the root. GetParentId is
- // how you find a node's parent.
- int64 GetParentId() const;
-
- // Nodes are either folders or not. This corresponds to the IS_DIR property
- // of syncable::Entry.
- bool GetIsFolder() const;
-
- // Returns the title of the object as a C string. The memory is owned by
- // BaseNode and becomes invalid if GetTitle() is called a second time on this
- // node, or when the node is destroyed. A caller should convert this
- // immediately into e.g. a std::string. Uniqueness of the title is not
- // enforced on siblings -- it is not an error for two children to share
- // a title.
- const sync_char16* GetTitle() const;
-
- // Returns the URL of a bookmark object as a C string. The memory is owned
- // by BaseNode and becomes invalid if GetURL() is called a second time on
- // this node, or when the node is destroyed. A caller should convert this
- // immediately into e.g. a std::string.
- const sync_char16* GetURL() const;
-
- // Return a pointer to the byte data of the favicon image for this node.
- // Will return NULL if there is no favicon data associated with this node.
- // The length of the array is returned to the caller via |size_in_bytes|.
- // Favicons are expected to be PNG images, and though no verification is
- // done on the syncapi client of this, the server may reject favicon updates
- // that are invalid for whatever reason.
- const unsigned char* GetFaviconBytes(size_t* size_in_bytes);
-
- // Returns the local external ID associated with the node.
- int64 GetExternalId() const;
-
- // Return the ID of the node immediately before this in the sibling order.
- // For the first node in the ordering, return 0.
- int64 GetPredecessorId() const;
-
- // Return the ID of the node immediately after this in the sibling order.
- // For the last node in the ordering, return 0.
- int64 GetSuccessorId() const;
-
- // Return the ID of the first child of this node. If this node has no
- // children, return 0.
- int64 GetFirstChildId() const;
-
- // Get an array containing the IDs of this node's children. The memory is
- // owned by BaseNode and becomes invalid if GetChildIds() is called a second
- // time on this node, or when the node is destroyed. Return the array size
- // in the child_count parameter.
- const int64* GetChildIds(size_t* child_count) const;
-
- // These virtual accessors provide access to data members of derived classes.
- virtual const syncable::Entry* GetEntry() const = 0;
- virtual const BaseTransaction* GetTransaction() const = 0;
-
- protected:
- BaseNode();
- virtual ~BaseNode();
-
- private:
- struct BaseNodeInternal;
-
- // Node is meant for stack use only.
- void* operator new(size_t size);
-
- // Provides storage for member functions that return pointers to class
- // memory, e.g. C strings returned by GetTitle().
- BaseNodeInternal* data_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseNode);
-};
-
-// WriteNode extends BaseNode to add mutation, and wraps
-// syncable::MutableEntry. A WriteTransaction is needed to create a WriteNode.
-class SYNC_EXPORT WriteNode : public BaseNode {
- public:
- // Create a WriteNode using the given transaction.
- explicit WriteNode(WriteTransaction* transaction);
- virtual ~WriteNode();
-
- // A client must use one (and only one) of the following Init variants to
- // populate the node.
-
- // BaseNode implementation.
- virtual bool InitByIdLookup(int64 id);
-
- // Create a new node with the specified parent and predecessor. Use a NULL
- // |predecessor| to indicate that this is to be the first child.
- // |predecessor| must be a child of |new_parent| or NULL. Returns false on
- // failure.
- bool InitByCreation(const BaseNode& parent, const BaseNode* predecessor);
-
- // These Set() functions correspond to the Get() functions of BaseNode.
- void SetIsFolder(bool folder);
- void SetTitle(const sync_char16* title);
- void SetURL(const sync_char16* url);
- void SetFaviconBytes(const unsigned char* bytes, size_t size_in_bytes);
- // External ID is a client-only field, so setting it doesn't cause the item to
- // be synced again.
- void SetExternalId(int64 external_id);
-
- // Remove this node and its children.
- void Remove();
-
- // Set a new parent and position. Position is specified by |predecessor|; if
- // it is NULL, the node is moved to the first position. |predecessor| must
- // be a child of |new_parent| or NULL. Returns false on failure..
- bool SetPosition(const BaseNode& new_parent, const BaseNode* predecessor);
-
- // Implementation of BaseNode's abstract virtual accessors.
- virtual const syncable::Entry* GetEntry() const;
-
- virtual const BaseTransaction* GetTransaction() const;
-
- private:
- void* operator new(size_t size); // Node is meant for stack use only.
-
- // Helper to set the previous node.
- void PutPredecessor(const BaseNode* predecessor);
-
- // Sets IS_UNSYNCED and SYNCING to ensure this entry is considered in an
- // upcoming commit pass.
- void MarkForSyncing();
-
- // The underlying syncable object which this class wraps.
- syncable::MutableEntry* entry_;
-
- // The sync API transaction that is the parent of this node.
- WriteTransaction* transaction_;
-
- DISALLOW_COPY_AND_ASSIGN(WriteNode);
-};
-
-// ReadNode wraps a syncable::Entry to provide the functionality of a
-// read-only BaseNode.
-class SYNC_EXPORT ReadNode : public BaseNode {
- public:
- // Create an unpopulated ReadNode on the given transaction. Call some flavor
- // of Init to populate the ReadNode with a database entry.
- explicit ReadNode(const BaseTransaction* transaction);
- virtual ~ReadNode();
-
- // A client must use one (and only one) of the following Init variants to
- // populate the node.
-
- // BaseNode implementation.
- virtual bool InitByIdLookup(int64 id);
-
- // There is always a root node, so this can't fail. The root node is
- // never mutable, so root lookup is only possible on a ReadNode.
- void InitByRootLookup();
-
- // Each server-created permanent node is tagged with a unique string.
- // Look up the node with the particular tag. If it does not exist,
- // return false. Since these nodes are special, lookup is only
- // provided only through ReadNode.
- bool InitByTagLookup(const sync_char16* tag);
-
- // Implementation of BaseNode's abstract virtual accessors.
- virtual const syncable::Entry* GetEntry() const;
- virtual const BaseTransaction* GetTransaction() const;
-
- private:
- void* operator new(size_t size); // Node is meant for stack use only.
-
- // The underlying syncable object which this class wraps.
- syncable::Entry* entry_;
-
- // The sync API transaction that is the parent of this node.
- const BaseTransaction* transaction_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadNode);
-};
-
-// Sync API's BaseTransaction, ReadTransaction, and WriteTransaction allow for
-// batching of several read and/or write operations. The read and write
-// operations are performed by creating ReadNode and WriteNode instances using
-// the transaction. These transaction classes wrap identically named classes in
-// syncable, and are used in a similar way. Unlike syncable::BaseTransaction,
-// whose construction requires an explicit syncable::ScopedDirLookup, a sync
-// API BaseTransaction creates its own ScopedDirLookup implicitly.
-class SYNC_EXPORT BaseTransaction {
- public:
- // Provide access to the underlying syncable.h objects from BaseNode.
- virtual syncable::BaseTransaction* GetWrappedTrans() const = 0;
- const syncable::ScopedDirLookup& GetLookup() const { return *lookup_; }
-
- protected:
- // The ScopedDirLookup is created in the constructor and destroyed
- // in the destructor. Creation of the ScopedDirLookup is not expected
- // to fail.
- explicit BaseTransaction(UserShare* share);
- virtual ~BaseTransaction();
-
- private:
- // A syncable ScopedDirLookup, which is the parent of syncable transactions.
- syncable::ScopedDirLookup* lookup_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseTransaction);
-};
-
-// Sync API's ReadTransaction is a read-only BaseTransaction. It wraps
-// a syncable::ReadTransaction.
-class SYNC_EXPORT ReadTransaction : public BaseTransaction {
- public:
- // Start a new read-only transaction on the specified repository.
- explicit ReadTransaction(UserShare* share);
- virtual ~ReadTransaction();
-
- // BaseTransaction override.
- virtual syncable::BaseTransaction* GetWrappedTrans() const;
- private:
- void* operator new(size_t size); // Transaction is meant for stack use only.
-
- // The underlying syncable object which this class wraps.
- syncable::ReadTransaction* transaction_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadTransaction);
-};
-
-// Sync API's WriteTransaction is a read/write BaseTransaction. It wraps
-// a syncable::WriteTransaction.
-class SYNC_EXPORT WriteTransaction : public BaseTransaction {
- public:
- // Start a new read/write transaction.
- explicit WriteTransaction(UserShare* share);
- virtual ~WriteTransaction();
-
- // Provide access to the syncable.h transaction from the API WriteNode.
- virtual syncable::BaseTransaction* GetWrappedTrans() const;
- syncable::WriteTransaction* GetWrappedWriteTrans() { return transaction_; }
-
- private:
- void* operator new(size_t size); // Transaction is meant for stack use only.
-
- // The underlying syncable object which this class wraps.
- syncable::WriteTransaction* transaction_;
-
- DISALLOW_COPY_AND_ASSIGN(WriteTransaction);
-};
-
-// SyncManager encapsulates syncable::DirectoryManager and serves as the parent
-// of all other objects in the sync API. SyncManager is thread-safe. If
-// multiple threads interact with the same local sync repository (i.e. the
-// same sqlite database), they should share a single SyncManager instance. The
-// caller should typically create one SyncManager for the lifetime of a user
-// session.
-class SYNC_EXPORT SyncManager {
- public:
- // SyncInternal contains the implementation of SyncManager, while abstracting
- // internal types from clients of the interface.
- class SyncInternal;
-
- // ChangeRecord indicates a single item that changed as a result of a sync
- // operation. This gives the sync id of the node that changed, and the type
- // of change. To get the actual property values after an ADD or UPDATE, the
- // client should get the node with InitByIdLookup(), using the provided id.
- struct ChangeRecord {
- enum Action {
- ACTION_ADD,
- ACTION_DELETE,
- ACTION_UPDATE,
- };
- ChangeRecord() : id(kInvalidId), action(ACTION_ADD) {}
- int64 id;
- Action action;
- };
-
- // When the SyncManager is unable to initiate the syncing process due to a
- // failure during authentication, AuthProblem describes the actual problem
- // more precisely.
- enum AuthProblem {
- AUTH_PROBLEM_NONE = 0,
- // The credentials supplied to GAIA were either invalid, or the locally
- // cached credentials have expired. If this happens, the sync system
- // will continue as if offline until authentication is reattempted.
- AUTH_PROBLEM_INVALID_GAIA_CREDENTIALS,
- // The GAIA user is not authorized to use the sync service.
- AUTH_PROBLEM_USER_NOT_SIGNED_UP,
- // Could not connect to server to verify credentials. This could be in
- // response to either failure to connect to GAIA or failure to connect to
- // the sync service during authentication.
- AUTH_PROBLEM_CONNECTION_FAILED,
- };
-
- // Status encapsulates detailed state about the internals of the SyncManager.
- struct Status {
- // Summary is a distilled set of important information that the end-user may
- // wish to be informed about (through UI, for example). Note that if a
- // summary state requires user interaction (such as auth failures), more
- // detailed information may be contained in additional status fields.
- enum Summary {
- // The internal instance is in an unrecognizable state. This should not
- // happen.
- INVALID = 0,
- // Can't connect to server, but there are no pending changes in
- // our local cache.
- OFFLINE,
- // Can't connect to server, and there are pending changes in our
- // local cache.
- OFFLINE_UNSYNCED,
- // Connected and syncing.
- SYNCING,
- // Connected, no pending changes.
- READY,
- // User has chosen to pause syncing.
- PAUSED,
- // Internal sync error.
- CONFLICT,
- // Can't connect to server, and we haven't completed the initial
- // sync yet. So there's nothing we can do but wait for the server.
- OFFLINE_UNUSABLE,
- };
- Summary summary;
-
- // Various server related information.
- bool authenticated; // Successfully authenticated via GAIA.
- bool server_up; // True if we have received at least one good
- // reply from the server.
- bool server_reachable; // True if we received any reply from the server.
- bool server_broken; // True of the syncer is stopped because of server
- // issues.
-
- bool notifications_enabled; // True only if subscribed for notifications.
- int notifications_received;
- int notifications_sent;
-
- // Various Syncer data.
- int unsynced_count;
- int conflicting_count;
- bool syncing;
- bool syncer_paused;
- bool initial_sync_ended;
- bool syncer_stuck;
- int64 updates_available;
- int64 updates_received;
- bool disk_full;
- bool invalid_store;
- int max_consecutive_errors; // The max number of errors from any component.
- };
-
- // An interface the embedding application implements to receive notifications
- // from the SyncManager. Register an observer via SyncManager::AddObserver.
- // This observer is an event driven model as the events may be raised from
- // different internal threads, and simply providing an "OnStatusChanged" type
- // notification complicates things such as trying to determine "what changed",
- // if different members of the Status object are modified from different
- // threads. This way, the event is explicit, and it is safe for the Observer
- // to dispatch to a native thread or synchronize accordingly.
- class Observer {
- public:
- Observer() { }
- virtual ~Observer() { }
- // Notify the observer that changes have been applied to the sync model.
- // This will be invoked on the same thread as on which ApplyChanges was
- // called. |changes| is an array of size |change_count|, and contains the ID
- // of each individual item that was changed. |changes| exists only
- // for the duration of the call. Because the observer is passed a |trans|,
- // the observer can assume a read lock on the database that will be released
- // after the function returns.
- //
- // The SyncManager constructs |changes| in the following guaranteed order:
- //
- // 1. Deletions, from leaves up to parents.
- // 2. Updates to existing items with synced parents & predecessors.
- // 3. New items with synced parents & predecessors.
- // 4. Items with parents & predecessors in |changes|.
- // 5. Repeat #4 until all items are in |changes|.
- //
- // Thus, an implementation of OnChangesApplied should be able to
- // process the change records in the order without having to worry about
- // forward dependencies. But since deletions come before reparent
- // operations, a delete may temporarily orphan a node that is
- // updated later in the list.
- virtual void OnChangesApplied(const BaseTransaction* trans,
- const ChangeRecord* changes,
- int change_count) = 0;
-
- // A round-trip sync-cycle took place and the syncer has resolved any
- // conflicts that may have arisen. This is kept separate from
- // OnStatusChanged as there isn't really any state update; it is plainly
- // a notification of a state transition.
- virtual void OnSyncCycleCompleted() = 0;
-
- // Called when user interaction may be required due to an auth problem.
- virtual void OnAuthProblem(AuthProblem auth_problem) = 0;
-
- // Called when initialization is complete to the point that SyncManager can
- // process changes. This does not necessarily mean authentication succeeded
- // or that the SyncManager is online.
- // IMPORTANT: Creating any type of transaction before receiving this
- // notification is illegal!
- // WARNING: Calling methods on the SyncManager before receiving this
- // message, unless otherwise specified, produces undefined behavior.
- virtual void OnInitializationComplete() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Observer);
- };
-
- // Create an uninitialized SyncManager. Callers must Init() before using.
- SyncManager();
- virtual ~SyncManager();
-
- // Initialize the sync manager. |database_location| specifies the path of
- // the directory in which to locate a sqlite repository storing the syncer
- // backend state. Initialization will open the database, or create it if it
- // does not already exist. Returns false on failure.
- // |sync_server_and_path| and |sync_server_port| represent the Chrome sync
- // server to use, and |use_ssl| specifies whether to communicate securely;
- // the default is false.
- // |gaia_service_id| is the service id used for GAIA authentication. If it's
- // null then default will be used.
- // |post_factory| will be owned internally and used to create
- // instances of an HttpPostProvider.
- // |auth_post_factory| will be owned internally and used to create
- // instances of an HttpPostProvider for communicating with GAIA.
- // TODO(timsteele): It seems like one factory should suffice, but for now to
- // avoid having to deal with threading issues since the auth code and syncer
- // code live on separate threads that run simultaneously, we just dedicate
- // one to each component. Long term we may want to reconsider the HttpBridge
- // API to take all the params in one chunk in a threadsafe manner.. which is
- // still suboptimal as there will be high contention between the two threads
- // on startup; so maybe what we have now is the best solution- it does mirror
- // the CURL implementation as each thread creates their own internet handle.
- // Investigate.
- // |model_safe_worker| ownership is given to the SyncManager.
- // |user_agent| is a 7-bit ASCII string suitable for use as the User-Agent
- // HTTP header. Used internally when collecting stats to classify clients.
- bool Init(const sync_char16* database_location,
- const char* sync_server_and_path,
- int sync_server_port,
- const char* gaia_service_id,
- const char* gaia_source,
- bool use_ssl,
- HttpPostProviderFactory* post_factory,
- HttpPostProviderFactory* auth_post_factory,
- ModelSafeWorkerInterface* model_safe_worker,
- bool attempt_last_user_authentication,
- const char* user_agent);
-
- // Returns the username last used for a successful authentication as a
- // null-terminated string. Returns empty if there is no such username.
- // The memory is not owned by the caller and should be copied.
- const char* GetAuthenticatedUsername();
-
- // Submit credentials to GAIA for verification and start the
- // syncing process on success. On success, both |username| and the obtained
- // auth token are persisted on disk for future re-use.
- // If authentication fails, OnAuthProblem is called on our Observer.
- // The Observer may, in turn, decide to try again with new
- // credentials. Calling this method again is the appropriate course of action
- // to "retry".
- // |username| and |password| are expected to be owned by the caller.
- void Authenticate(const char* username, const char* password);
-
- // Adds a listener to be notified of sync events.
- // NOTE: It is OK (in fact, it's probably a good idea) to call this before
- // having received OnInitializationCompleted.
- void SetObserver(Observer* observer);
-
- // Remove the observer set by SetObserver (no op if none was set).
- // Make sure to call this if the Observer set in SetObserver is being
- // destroyed so the SyncManager doesn't potentially dereference garbage.
- void RemoveObserver();
-
- // Status-related getters. Typically GetStatusSummary will suffice, but
- // GetDetailedSyncStatus can be useful for gathering debug-level details of
- // the internals of the sync engine.
- Status::Summary GetStatusSummary() const;
- Status GetDetailedStatus() const;
-
- // Get the internal implementation for use by BaseTransaction, etc.
- SyncInternal* GetImpl() const;
-
- // Call periodically from a database-safe thread to persist recent changes
- // to the syncapi model.
- void SaveChanges();
-
- // Invoking this method will result in the syncapi bypassing authentication
- // and opening a local store suitable for testing client code. When in this
- // mode, nothing will ever get synced to a server (in fact no HTTP
- // communication will take place).
- // Note: The SyncManager precondition that you must first call Init holds;
- // this will fail unless we're initialized.
- void SetupForTestMode(const sync_char16* test_username);
-
- // Issue a final SaveChanges, close sqlite handles, and stop running threads.
- // Must be called from the same thread that called Init().
- void Shutdown();
-
- UserShare* GetUserShare() const;
-
- private:
- // An opaque pointer to the nested private class.
- SyncInternal* data_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncManager);
-};
-
-// An interface the embedding application (e.g. Chromium) implements to
-// provide required HTTP POST functionality to the syncer backend.
-// This interface is designed for one-time use. You create one, use it, and
-// create another if you want to make a subsequent POST.
-// TODO(timsteele): Bug 1482576. Consider splitting syncapi.h into two files:
-// one for the API defining the exports, which doesn't need to be included from
-// anywhere internally, and another file for the interfaces like this one.
-class HttpPostProviderInterface {
- public:
- HttpPostProviderInterface() { }
- virtual ~HttpPostProviderInterface() { }
-
- // Use specified user agent string when POSTing. If not called a default UA
- // may be used.
- virtual void SetUserAgent(const char* user_agent) = 0;
-
- // Set the URL to POST to.
- virtual void SetURL(const char* url, int port) = 0;
-
- // Set the type, length and content of the POST payload.
- // |content_type| is a null-terminated MIME type specifier.
- // |content| is a data buffer; Do not interpret as a null-terminated string.
- // |content_length| is the total number of chars in |content|. It is used to
- // assign/copy |content| data.
- virtual void SetPostPayload(const char* content_type, int content_length,
- const char* content) = 0;
-
- // Add the specified cookie to the request context using the url set by
- // SetURL as the key. |cookie| should be a standard cookie line
- // [e.g "name=val; name2=val2"]. |cookie| should be copied.
- virtual void AddCookieForRequest(const char* cookie) = 0;
-
- // Returns true if the URL request succeeded. If the request failed,
- // os_error() may be non-zero and hence contain more information.
- virtual bool MakeSynchronousPost(int* os_error_code, int* response_code) = 0;
-
- // Get the length of the content returned in the HTTP response.
- // This does not count the trailing null-terminating character returned
- // by GetResponseContent, so it is analogous to calling string.length.
- virtual int GetResponseContentLength() const = 0;
-
- // Get the content returned in the HTTP response.
- // This is a null terminated string of characters.
- // Value should be copied.
- virtual const char* GetResponseContent() const = 0;
-
- // To simplify passing a vector<string> across this API, we provide the
- // following two methods. Use GetResponseCookieCount to bound a loop calling
- // GetResponseCookieAt once for each integer in the range
- // [0, GetNumCookiesInResponse). The char* returned should be copied.
- virtual int GetResponseCookieCount() const = 0;
- virtual const char* GetResponseCookieAt(int cookie_number) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HttpPostProviderInterface);
-};
-
-// A factory to create HttpPostProviders to hide details about the
-// implementations and dependencies.
-// A factory instance itself should be owned by whomever uses it to create
-// HttpPostProviders.
-class HttpPostProviderFactory {
- public:
- // Obtain a new HttpPostProviderInterface instance, owned by caller.
- virtual HttpPostProviderInterface* Create() = 0;
-
- // When the interface is no longer needed (ready to be cleaned up), clients
- // must call Destroy().
- // This allows actual HttpPostProvider subclass implementations to be
- // reference counted, which is useful if a particular implementation uses
- // multiple threads to serve network requests.
- virtual void Destroy(HttpPostProviderInterface* http) = 0;
- virtual ~HttpPostProviderFactory() { }
-};
-
-// A class syncapi clients should use whenever the underlying model is bound to
-// a particular thread in the embedding application. This exposes an interface
-// by which any model-modifying invocations will be forwarded to the
-// appropriate thread in the embedding application.
-// "model safe" refers to not allowing an embedding application model to fall
-// out of sync with the syncable::Directory due to race conditions.
-class ModelSafeWorkerInterface {
- public:
- virtual ~ModelSafeWorkerInterface() { }
- // A Visitor is passed to CallDoWorkFromModelSafeThreadAndWait invocations,
- // and it's sole purpose is to provide a way for the ModelSafeWorkerInterface
- // implementation to actually _do_ the work required, by calling the only
- // method on this class, DoWork().
- class Visitor {
- public:
- virtual ~Visitor() { }
- // When on a model safe thread, this should be called to have the syncapi
- // actually perform the work needing to be done.
- virtual void DoWork() = 0;
- };
- // Subclasses should implement to invoke DoWork on |visitor| once on a thread
- // appropriate for data model modifications.
- // While it doesn't hurt, the impl does not need to be re-entrant (for now).
- // Note: |visitor| is owned by caller.
- virtual void CallDoWorkFromModelSafeThreadAndWait(Visitor* visitor) = 0;
-};
-
-} // namespace sync_api
-
-#endif // CHROME_BROWSER_SYNC_ENGINE_SYNCAPI_H_
diff --git a/chrome/browser/sync/glue/bookmark_model_worker.cc b/chrome/browser/sync/glue/bookmark_model_worker.cc
deleted file mode 100644
index be97167..0000000
--- a/chrome/browser/sync/glue/bookmark_model_worker.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "chrome/browser/sync/glue/bookmark_model_worker.h"
-
-#include "base/message_loop.h"
-#include "base/waitable_event.h"
-
-namespace browser_sync {
-
-void BookmarkModelWorker::CallDoWorkFromModelSafeThreadAndWait(
- ModelSafeWorkerInterface::Visitor* visitor) {
- // It is possible this gets called when we are in the STOPPING state, because
- // the UI loop has initiated shutdown but the syncer hasn't got the memo yet.
- // This is fine, the work will get scheduled and run normally or run by our
- // code handling this case in Stop().
- DCHECK_NE(state_, STOPPED);
- if (state_ == STOPPED)
- return;
- if (MessageLoop::current() == bookmark_model_loop_) {
- DLOG(WARNING) << "CallDoWorkFromModelSafeThreadAndWait called from "
- << "bookmark_model_loop_. Probably a nested invocation?";
- visitor->DoWork();
- return;
- }
-
- // Create an unsignaled event to wait on.
- base::WaitableEvent work_done(false, false);
- {
- // We lock only to avoid PostTask'ing a NULL pending_work_ (because it
- // could get Run() in Stop() and call OnTaskCompleted before we post).
- // The task is owned by the message loop as per usual.
- AutoLock lock(pending_work_lock_);
- DCHECK(!pending_work_);
- pending_work_ = new CallDoWorkAndSignalTask(visitor, &work_done, this);
- bookmark_model_loop_->PostTask(FROM_HERE, pending_work_);
- }
- syncapi_event_.Signal(); // Notify that the syncapi produced work for us.
- work_done.Wait();
-}
-
-BookmarkModelWorker::~BookmarkModelWorker() {
- DCHECK_EQ(state_, STOPPED);
-}
-
-void BookmarkModelWorker::OnSyncerShutdownComplete() {
- // The SyncerThread has terminated and we are no longer needed by syncapi.
- // The UI loop initiated shutdown and is (or will be) waiting in Stop().
- // We could either be WORKING or RUNNING_MANUAL_SHUTDOWN_PUMP, depending
- // on where we timeslice the UI thread in Stop; but we can't be STOPPED,
- // because that would imply NotifySyncapiShutdownComplete already signaled.
- DCHECK_NE(state_, STOPPED);
-
- syncapi_has_shutdown_ = true;
- syncapi_event_.Signal();
-}
-
-void BookmarkModelWorker::Stop() {
- DCHECK_EQ(MessageLoop::current(), bookmark_model_loop_);
- DCHECK_EQ(state_, WORKING);
-
- // We're on our own now, the beloved UI MessageLoop is no longer running.
- // Any tasks scheduled or to be scheduled on the UI MessageLoop will not run.
- state_ = RUNNING_MANUAL_SHUTDOWN_PUMP;
-
- // Drain any final task manually until the SyncerThread tells us it has
- // totally finished. Note we use a 'while' loop and not 'if'. The main subtle
- // reason for this is that syncapi_event could be signaled the first time we
- // come through due to an old CallDoWork call, and we need to keep looping
- // until the SyncerThread either calls it again or tells us it is done. There
- // should only ever be 0 or 1 tasks Run() here, however.
- while (!syncapi_has_shutdown_) {
- {
- AutoLock lock(pending_work_lock_);
- if (pending_work_)
- pending_work_->Run();
- }
- syncapi_event_.Wait(); // Signaled either by new task, or SyncerThread
- // termination.
- }
-
- state_ = STOPPED;
-}
-
-void BookmarkModelWorker::CallDoWorkAndSignalTask::Run() {
- if (!visitor_) {
- // This can happen during tests or cases where there are more than just the
- // default BookmarkModelWorker in existence and it gets destroyed before
- // the main UI loop has terminated. There is no easy way to assert the
- // loop is running / not running at the moment, so we just provide cancel
- // semantics here and short-circuit.
- // TODO(timsteele): Maybe we should have the message loop destruction
- // observer fire when the loop has ended, just a bit before it
- // actually gets destroyed.
- return;
- }
- visitor_->DoWork();
-
- // Sever ties with visitor_ to allow the sanity-checking above that we don't
- // get run twice.
- visitor_ = NULL;
-
- // Notify the BookmarkModelWorker that scheduled us that we have run
- // successfully.
- scheduler_->OnTaskCompleted();
- work_done_->Signal(); // Unblock the syncer thread that scheduled us.
-}
-
-} // namespace browser_sync
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/bookmark_model_worker.h b/chrome/browser/sync/glue/bookmark_model_worker.h
deleted file mode 100644
index 4ddb5f8..0000000
--- a/chrome/browser/sync/glue/bookmark_model_worker.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_
-#define CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_
-
-#include "base/lock.h"
-#include "base/task.h"
-#include "base/waitable_event.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-
-class MessageLoop;
-
-namespace browser_sync {
-
-// A ModelSafeWorker for bookmarks that accepts work requests from the syncapi
-// that need to be fulfilled from the MessageLoop home to the BookmarkModel
-// (this is typically the "main" UI thread).
-//
-// Lifetime note: Instances of this class will generally be owned by the
-// SyncerThread. When the SyncerThread _object_ is destroyed, the
-// BookmarkModelWorker will be destroyed. The SyncerThread object is destroyed
-// after the actual syncer pthread has exited.
-class BookmarkModelWorker :
- public sync_api::ModelSafeWorkerInterface {
- public:
- explicit BookmarkModelWorker(MessageLoop* bookmark_model_loop)
- : state_(WORKING),
- pending_work_(NULL),
- syncapi_has_shutdown_(false),
- bookmark_model_loop_(bookmark_model_loop),
- syncapi_event_(false, false) {
- }
- virtual ~BookmarkModelWorker();
-
- // A simple task to signal a waitable event after calling DoWork on a visitor.
- class CallDoWorkAndSignalTask : public Task {
- public:
- CallDoWorkAndSignalTask(ModelSafeWorkerInterface::Visitor* visitor,
- base::WaitableEvent* work_done,
- BookmarkModelWorker* scheduler)
- : visitor_(visitor), work_done_(work_done), scheduler_(scheduler) {
- }
- virtual ~CallDoWorkAndSignalTask() { }
-
- // Task implementation.
- virtual void Run();
-
- private:
- // Task data - a visitor that knows how to DoWork, and a waitable event
- // to signal after the work has been done.
- ModelSafeWorkerInterface::Visitor* visitor_;
- base::WaitableEvent* work_done_;
-
- // The BookmarkModelWorker responsible for scheduling us.
- BookmarkModelWorker* const scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(CallDoWorkAndSignalTask);
- };
-
- // Called by the UI thread on shutdown of the sync service. Blocks until
- // the BookmarkModelWorker has safely met termination conditions, namely that
- // no task scheduled by CallDoWorkFromModelSafeThreadAndWait remains un-
- // processed and that syncapi will not schedule any further work for us to do.
- void Stop();
-
- // ModelSafeWorkerInterface implementation. Called on syncapi SyncerThread.
- virtual void CallDoWorkFromModelSafeThreadAndWait(
- ModelSafeWorkerInterface::Visitor* visitor);
-
- // Upon receiving this idempotent call, the ModelSafeWorkerInterface can
- // assume no work will ever be scheduled again from now on. If it has any work
- // that it has not yet completed, it must make sure to run it as soon as
- // possible as the Syncer is trying to shut down. Called from the CoreThread.
- void OnSyncerShutdownComplete();
-
- // Callback from |pending_work_| to notify us that it has been run.
- // Called on |bookmark_model_loop_|.
- void OnTaskCompleted() { pending_work_ = NULL; }
-
- private:
- // The life-cycle of a BookmarkModelWorker in three states.
- enum State {
- // We hit the ground running in this state and remain until
- // the UI loop calls Stop().
- WORKING,
- // Stop() sequence has been initiated, but we have not received word that
- // the SyncerThread has terminated and doesn't need us anymore. Since the
- // UI MessageLoop is not running at this point, we manually process any
- // last pending_task_ that the Syncer throws at us, effectively dedicating
- // the UI thread to terminating the Syncer.
- RUNNING_MANUAL_SHUTDOWN_PUMP,
- // We have come to a complete stop, no scheduled work remains, and no work
- // will be scheduled from now until our destruction.
- STOPPED,
- };
-
- // This is set by the UI thread, but is not explicitly thread safe, so only
- // read this value from other threads when you know it is absolutely safe (e.g
- // there is _no_ way we can be in CallDoWork with state_ = STOPPED, so it is
- // safe to read / compare in this case).
- State state_;
-
- // We keep a reference to any task we have scheduled so we can gracefully
- // force them to run if the syncer is trying to shutdown.
- Task* pending_work_;
- Lock pending_work_lock_;
-
- // Set by the SyncCoreThread when Syncapi shutdown has completed and the
- // SyncerThread has terminated, so no more work will be scheduled. Read by
- // the UI thread in Stop().
- bool syncapi_has_shutdown_;
-
- // The BookmarkModel's home-sweet-home MessageLoop.
- MessageLoop* const bookmark_model_loop_;
-
- // Used as a barrier at shutdown to ensure the SyncerThread terminates before
- // we allow the UI thread to return from Stop(). This gets signalled whenever
- // one of two events occur: a new pending_work_ task was scheduled, or the
- // SyncerThread has terminated. We only care about (1) when we are in Stop(),
- // because we have to manually Run() the task.
- base::WaitableEvent syncapi_event_;
-
- DISALLOW_COPY_AND_ASSIGN(BookmarkModelWorker);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_BOOKMARK_MODEL_WORKER_H_
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/bookmark_model_worker_unittest.cc b/chrome/browser/sync/glue/bookmark_model_worker_unittest.cc
deleted file mode 100644
index ad674a8..0000000
--- a/chrome/browser/sync/glue/bookmark_model_worker_unittest.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2006-2009 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.
-#ifdef CHROME_PERSONALIZATION
-
-#include "base/thread.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/bookmark_model_worker.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using browser_sync::BookmarkModelWorker;
-using namespace sync_api;
-
-// Various boilerplate, primarily for the StopWithPendingWork test.
-
-class BookmarkModelWorkerVisitor : public ModelSafeWorkerInterface::Visitor {
- public:
- BookmarkModelWorkerVisitor(MessageLoop* faux_ui_loop,
- base::WaitableEvent* was_run,
- bool quit_loop)
- : faux_ui_loop_(faux_ui_loop), quit_loop_when_run_(quit_loop),
- was_run_(was_run) { }
- virtual ~BookmarkModelWorkerVisitor() { }
-
- virtual void DoWork() {
- EXPECT_EQ(MessageLoop::current(), faux_ui_loop_);
- was_run_->Signal();
- if (quit_loop_when_run_)
- MessageLoop::current()->Quit();
- }
-
- private:
- MessageLoop* faux_ui_loop_;
- bool quit_loop_when_run_;
- base::WaitableEvent* was_run_;
- DISALLOW_COPY_AND_ASSIGN(BookmarkModelWorkerVisitor);
-};
-
-// A faux-syncer that only interacts with its model safe worker.
-class Syncer {
- public:
- explicit Syncer(BookmarkModelWorker* worker) : worker_(worker){ }
- ~Syncer() { }
-
- void SyncShare(BookmarkModelWorkerVisitor* visitor) {
- worker_->CallDoWorkFromModelSafeThreadAndWait(visitor);
- }
- private:
- BookmarkModelWorker* worker_;
- DISALLOW_COPY_AND_ASSIGN(Syncer);
-};
-
-// A task run from the SyncerThread to "sync share", ie tell the Syncer to
-// ask it's ModelSafeWorker to do something.
-class FakeSyncShareTask : public Task {
- public:
- FakeSyncShareTask(Syncer* syncer, BookmarkModelWorkerVisitor* visitor)
- : syncer_(syncer), visitor_(visitor) {
- }
- virtual void Run() {
- syncer_->SyncShare(visitor_);
- }
- private:
- Syncer* syncer_;
- BookmarkModelWorkerVisitor* visitor_;
- DISALLOW_COPY_AND_ASSIGN(FakeSyncShareTask);
-};
-
-// A task run from the CoreThread to simulate terminating syncapi.
-class FakeSyncapiShutdownTask : public Task {
- public:
- FakeSyncapiShutdownTask(base::Thread* syncer_thread,
- BookmarkModelWorker* worker,
- base::WaitableEvent** jobs,
- size_t job_count)
- : syncer_thread_(syncer_thread), worker_(worker), jobs_(jobs),
- job_count_(job_count), all_jobs_done_(false, false) { }
- virtual void Run() {
- // In real life, we would try and close a sync directory, which would
- // result in the syncer calling it's own destructor, which results in
- // the SyncerThread::HaltSyncer being called, which sets the
- // syncer in RequestEarlyExit mode and waits until the Syncer finishes
- // SyncShare to remove the syncer from it's watch. Here we just manually
- // wait until all outstanding jobs are done to simulate what happens in
- // SyncerThread::HaltSyncer.
- all_jobs_done_.WaitMany(jobs_, job_count_);
-
- // These two calls are made from SyncBackendHost::Core::DoShutdown.
- syncer_thread_->Stop();
- worker_->OnSyncerShutdownComplete();
- }
- private:
- base::Thread* syncer_thread_;
- BookmarkModelWorker* worker_;
- base::WaitableEvent** jobs_;
- size_t job_count_;
- base::WaitableEvent all_jobs_done_;
- DISALLOW_COPY_AND_ASSIGN(FakeSyncapiShutdownTask);
-};
-
-class BookmarkModelWorkerTest : public testing::Test {
- public:
- BookmarkModelWorkerTest() : faux_syncer_thread_("FauxSyncerThread"),
- faux_core_thread_("FauxCoreThread") { }
-
- virtual void SetUp() {
- faux_syncer_thread_.Start();
- bmw_.reset(new BookmarkModelWorker(&faux_ui_loop_));
- syncer_.reset(new Syncer(bmw_.get()));
- }
-
- Syncer* syncer() { return syncer_.get(); }
- BookmarkModelWorker* bmw() { return bmw_.get(); }
- base::Thread* core_thread() { return &faux_core_thread_; }
- base::Thread* syncer_thread() { return &faux_syncer_thread_; }
- MessageLoop* ui_loop() { return &faux_ui_loop_; }
- private:
- MessageLoop faux_ui_loop_;
- base::Thread faux_syncer_thread_;
- base::Thread faux_core_thread_;
- scoped_ptr<BookmarkModelWorker> bmw_;
- scoped_ptr<Syncer> syncer_;
-};
-
-TEST_F(BookmarkModelWorkerTest, ScheduledWorkRunsOnUILoop) {
- base::WaitableEvent v_was_run(false, false);
- scoped_ptr<BookmarkModelWorkerVisitor> v(
- new BookmarkModelWorkerVisitor(ui_loop(), &v_was_run, true));
-
- syncer_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncShareTask(syncer(), v.get()));
-
- // We are on the UI thread, so run our loop to process the
- // (hopefully) scheduled task from a SyncShare invocation.
- MessageLoop::current()->Run();
-
- bmw()->OnSyncerShutdownComplete();
- bmw()->Stop();
- syncer_thread()->Stop();
-}
-
-TEST_F(BookmarkModelWorkerTest, StopWithPendingWork) {
- // What we want to set up is the following:
- // ("ui_thread" is the thread we are currently executing on)
- // 1 - simulate the user shutting down the browser, and the ui thread needing
- // to terminate the core thread.
- // 2 - the core thread is where the syncapi is accessed from, and so it needs
- // to shut down the SyncerThread.
- // 3 - the syncer is waiting on the BookmarkModelWorker to
- // perform a task for it.
- // The BookmarkModelWorker's manual shutdown pump will save the day, as the
- // UI thread is not actually trying to join() the core thread, it is merely
- // waiting for the SyncerThread to give it work or to finish. After that, it
- // will join the core thread which should succeed as the SyncerThread has left
- // the building. Unfortunately this test as written is not provably decidable,
- // as it will always halt on success, but it may not on failure (namely if
- // the task scheduled by the Syncer is _never_ run).
- core_thread()->Start();
- base::WaitableEvent v_ran(false, false);
- scoped_ptr<BookmarkModelWorkerVisitor> v(new BookmarkModelWorkerVisitor(
- ui_loop(), &v_ran, false));
- base::WaitableEvent* jobs[] = { &v_ran };
-
- // The current message loop is not running, so queue a task to cause
- // BookmarkModelWorker::Stop() to play a crucial role. See comment below.
- syncer_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncShareTask(syncer(), v.get()));
-
- // This is what gets the core_thread blocked on the syncer_thread.
- core_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncapiShutdownTask(syncer_thread(), bmw(), jobs, 1));
-
- // This is what gets the UI thread blocked until NotifyExitRequested,
- // which is called when FakeSyncapiShutdownTask runs and deletes the syncer.
- bmw()->Stop();
-
- EXPECT_FALSE(syncer_thread()->IsRunning());
- core_thread()->Stop();
-}
-
-TEST_F(BookmarkModelWorkerTest, HypotheticalManualPumpFlooding) {
- // This situation should not happen in real life because the Syncer should
- // never send more than one CallDoWork notification after early_exit_requested
- // has been set, but our BookmarkModelWorker is built to handle this case
- // nonetheless. It may be needed in the future, and since we support it and
- // it is not actually exercised in the wild this test is essential.
- // It is identical to above except we schedule more than one visitor.
- core_thread()->Start();
-
- // Our ammunition.
- base::WaitableEvent fox1_ran(false, false);
- scoped_ptr<BookmarkModelWorkerVisitor> fox1(new BookmarkModelWorkerVisitor(
- ui_loop(), &fox1_ran, false));
- base::WaitableEvent fox2_ran(false, false);
- scoped_ptr<BookmarkModelWorkerVisitor> fox2(new BookmarkModelWorkerVisitor(
- ui_loop(), &fox2_ran, false));
- base::WaitableEvent fox3_ran(false, false);
- scoped_ptr<BookmarkModelWorkerVisitor> fox3(new BookmarkModelWorkerVisitor(
- ui_loop(), &fox3_ran, false));
- base::WaitableEvent* jobs[] = { &fox1_ran, &fox2_ran, &fox3_ran };
-
- // The current message loop is not running, so queue a task to cause
- // BookmarkModelWorker::Stop() to play a crucial role. See comment below.
- syncer_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncShareTask(syncer(), fox1.get()));
- syncer_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncShareTask(syncer(), fox2.get()));
-
- // This is what gets the core_thread blocked on the syncer_thread.
- core_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncapiShutdownTask(syncer_thread(), bmw(), jobs, 3));
- syncer_thread()->message_loop()->PostTask(FROM_HERE,
- new FakeSyncShareTask(syncer(), fox3.get()));
-
- // This is what gets the UI thread blocked until NotifyExitRequested,
- // which is called when FakeSyncapiShutdownTask runs and deletes the syncer.
- bmw()->Stop();
-
- // Was the thread killed?
- EXPECT_FALSE(syncer_thread()->IsRunning());
- core_thread()->Stop();
-}
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/http_bridge.cc b/chrome/browser/sync/glue/http_bridge.cc
deleted file mode 100644
index 1a01c87..0000000
--- a/chrome/browser/sync/glue/http_bridge.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "chrome/browser/sync/glue/http_bridge.h"
-
-#include "base/message_loop.h"
-#include "base/string_util.h"
-#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/profile.h"
-#include "net/base/cookie_monster.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_network_layer.h"
-#include "net/proxy/proxy_service.h"
-#include "net/url_request/url_request_status.h"
-#include "webkit/glue/webkit_glue.h"
-
-namespace browser_sync {
-
-HttpBridge::RequestContext* HttpBridgeFactory::GetRequestContext() {
- if (!request_context_) {
- request_context_ =
- new HttpBridge::RequestContext(Profile::GetDefaultRequestContext());
- request_context_->AddRef();
- }
- return request_context_;
-}
-
-HttpBridgeFactory::~HttpBridgeFactory() {
- if (request_context_) {
- // Clean up request context on IO thread.
- ChromeThread::GetMessageLoop(ChromeThread::IO)->ReleaseSoon(FROM_HERE,
- request_context_);
- request_context_ = NULL;
- }
-}
-
-sync_api::HttpPostProviderInterface* HttpBridgeFactory::Create() {
- // TODO(timsteele): We want the active profile request context.
- HttpBridge* http = new HttpBridge(GetRequestContext(),
- ChromeThread::GetMessageLoop(ChromeThread::IO));
- http->AddRef();
- return http;
-}
-
-void HttpBridgeFactory::Destroy(sync_api::HttpPostProviderInterface* http) {
- static_cast<HttpBridge*>(http)->Release();
-}
-
-HttpBridge::RequestContext::RequestContext(
- const URLRequestContext* baseline_context) {
-
- // Create empty, in-memory cookie store.
- cookie_store_ = new net::CookieMonster();
-
- // We don't use a cache for bridged loads, but we do want to share proxy info.
- host_resolver_ = baseline_context->host_resolver();
- proxy_service_ = baseline_context->proxy_service();
- http_transaction_factory_ =
- net::HttpNetworkLayer::CreateFactory(host_resolver_, proxy_service_);
-
- // TODO(timsteele): We don't currently listen for pref changes of these
- // fields or CookiePolicy; I'm not sure we want to strictly follow the
- // default settings, since for example if the user chooses to block all
- // cookies, sync will start failing. Also it seems like accept_lang/charset
- // should be tied to whatever the sync servers expect (if anything). These
- // fields should probably just be settable by sync backend; though we should
- // figure out if we need to give the user explicit control over policies etc.
- accept_language_ = baseline_context->accept_language();
- accept_charset_ = baseline_context->accept_charset();
-
- // We default to the browser's user agent. This can (and should) be overridden
- // with set_user_agent.
- user_agent_ = webkit_glue::GetUserAgent(GURL());
-}
-
-HttpBridge::RequestContext::~RequestContext() {
- delete cookie_store_;
- delete http_transaction_factory_;
-}
-
-HttpBridge::HttpBridge(HttpBridge::RequestContext* context,
- MessageLoop* io_loop)
- : context_for_request_(context),
- url_poster_(NULL),
- created_on_loop_(MessageLoop::current()),
- io_loop_(io_loop),
- request_completed_(false),
- request_succeeded_(false),
- http_response_code_(-1),
- http_post_completed_(false, false),
- use_io_loop_for_testing_(false) {
- context_for_request_->AddRef();
-}
-
-HttpBridge::~HttpBridge() {
- io_loop_->ReleaseSoon(FROM_HERE, context_for_request_);
-}
-
-void HttpBridge::SetUserAgent(const char* user_agent) {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(!request_completed_);
- context_for_request_->set_user_agent(user_agent);
-}
-
-void HttpBridge::SetURL(const char* url, int port) {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(!request_completed_);
- DCHECK(url_for_request_.is_empty())
- << "HttpBridge::SetURL called more than once?!";
- GURL temp(url);
- GURL::Replacements replacements;
- std::string port_str = IntToString(port);
- replacements.SetPort(port_str.c_str(),
- url_parse::Component(0, port_str.length()));
- url_for_request_ = temp.ReplaceComponents(replacements);
-}
-
-void HttpBridge::SetPostPayload(const char* content_type,
- int content_length,
- const char* content) {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(!request_completed_);
- DCHECK(content_type_.empty()) << "Bridge payload already set.";
- DCHECK_GE(content_length, 0) << "Content length < 0";
- content_type_ = content_type;
- if (!content || (content_length == 0)) {
- DCHECK_EQ(content_length, 0);
- request_content_ = " "; // TODO(timsteele): URLFetcher requires non-empty
- // content for POSTs whereas CURL does not, for now
- // we hack this to support the sync backend.
- } else {
- request_content_.assign(content, content_length);
- }
-}
-
-void HttpBridge::AddCookieForRequest(const char* cookie) {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(!request_completed_);
- DCHECK(url_for_request_.is_valid()) << "Valid URL not set.";
- if (!url_for_request_.is_valid()) return;
-
- if (!context_for_request_->cookie_store()->SetCookie(url_for_request_,
- cookie)) {
- DLOG(WARNING) << "Cookie " << cookie
- << " could not be added for url: " << url_for_request_ << ".";
- }
-}
-
-bool HttpBridge::MakeSynchronousPost(int* os_error_code, int* response_code) {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(!request_completed_);
- DCHECK(url_for_request_.is_valid()) << "Invalid URL for request";
- DCHECK(!content_type_.empty()) << "Payload not set";
- DCHECK(context_for_request_->is_user_agent_set()) << "User agent not set";
-
- io_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &HttpBridge::CallMakeAsynchronousPost));
-
- if (!http_post_completed_.Wait()) // Block until network request completes.
- NOTREACHED(); // See OnURLFetchComplete.
-
- DCHECK(request_completed_);
- *os_error_code = os_error_code_;
- *response_code = http_response_code_;
- return request_succeeded_;
-}
-
-void HttpBridge::MakeAsynchronousPost() {
- DCHECK_EQ(MessageLoop::current(), io_loop_);
- DCHECK(!request_completed_);
-
- url_poster_ = new URLFetcher(url_for_request_, URLFetcher::POST, this);
- url_poster_->set_request_context(context_for_request_);
- url_poster_->set_upload_data(content_type_, request_content_);
-
- if (use_io_loop_for_testing_)
- url_poster_->set_io_loop(io_loop_);
-
- url_poster_->Start();
-}
-
-int HttpBridge::GetResponseContentLength() const {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(request_completed_);
- return response_content_.size();
-}
-
-const char* HttpBridge::GetResponseContent() const {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(request_completed_);
- return response_content_.c_str();
-}
-
-int HttpBridge::GetResponseCookieCount() const {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(request_completed_);
- return response_cookies_.size();
-}
-
-const char* HttpBridge::GetResponseCookieAt(int cookie_number) const {
- DCHECK_EQ(MessageLoop::current(), created_on_loop_);
- DCHECK(request_completed_);
- bool valid_number = (cookie_number >= 0) &&
- (static_cast<size_t>(cookie_number) < response_cookies_.size());
- DCHECK(valid_number);
- if (!valid_number)
- return NULL;
- return response_cookies_[cookie_number].c_str();
-}
-
-void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url,
- const URLRequestStatus &status,
- int response_code,
- const ResponseCookies &cookies,
- const std::string &data) {
- DCHECK_EQ(MessageLoop::current(), io_loop_);
-
- request_completed_ = true;
- request_succeeded_ = (URLRequestStatus::SUCCESS == status.status());
- http_response_code_ = response_code;
- os_error_code_ = status.os_error();
-
- // TODO(timsteele): For now we need this "fixup" to match up with what the
- // sync backend expects. This seems to be non-standard and shouldn't be done
- // here in HttpBridge, and it breaks part of the unittest.
- for (size_t i = 0; i < cookies.size(); ++i) {
- net::CookieMonster::ParsedCookie parsed_cookie(cookies[i]);
- std::string cookie = " \t \t \t \t \t";
- cookie += parsed_cookie.Name() + "\t";
- cookie += parsed_cookie.Value();
- response_cookies_.push_back(cookie);
- }
-
- response_content_ = data;
-
- // End of the line for url_poster_. It lives only on the io_loop.
- // We defer deletion because we're inside a callback from a component of the
- // URLFetcher, so it seems most natural / "polite" to let the stack unwind.
- io_loop_->DeleteSoon(FROM_HERE, url_poster_);
- url_poster_ = NULL;
-
- // Wake the blocked syncer thread in MakeSynchronousPost.
- // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
- http_post_completed_.Signal();
-}
-
-} // namespace browser_sync
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/http_bridge.h b/chrome/browser/sync/glue/http_bridge.h
deleted file mode 100644
index 1e11e90..0000000
--- a/chrome/browser/sync/glue/http_bridge.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
-#define CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
-
-#include "base/ref_counted.h"
-#include "base/waitable_event.h"
-#include "chrome/browser/net/url_fetcher.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "googleurl/src/gurl.h"
-#include "net/url_request/url_request_context.h"
-#include "testing/gtest/include/gtest/gtest_prod.h"
-
-class MessageLoop;
-class HttpBridgeTest;
-
-namespace browser_sync {
-
-// A bridge between the syncer and Chromium HTTP layers.
-// Provides a way for the sync backend to use Chromium directly for HTTP
-// requests rather than depending on a third party provider (e.g libcurl).
-// This is a one-time use bridge. Create one for each request you want to make.
-// It is RefCountedThreadSafe because it can PostTask to the io loop, and thus
-// needs to stick around across context switches, etc.
-class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>,
- public sync_api::HttpPostProviderInterface,
- public URLFetcher::Delegate {
- public:
- // A request context used for HTTP requests bridged from the sync backend.
- // A bridged RequestContext has a dedicated in-memory cookie store and does
- // not use a cache. Thus the same type can be used for incognito mode.
- // TODO(timsteele): We subclass here instead of add a factory method on
- // ChromeURLRequestContext because:
- // 1) we want the ability to set_user_agent
- // 2) avoids ifdefs for now
- // 3) not sure we want to strictly follow settings for cookie policy,
- // accept lang/charset, since changing these could break syncing.
- class RequestContext : public URLRequestContext {
- public:
- // |baseline_context| is used to obtain the accept-language,
- // accept-charsets, and proxy service information for bridged requests.
- // Typically |baseline_context| should be the URLRequestContext of the
- // currently active profile.
- explicit RequestContext(const URLRequestContext* baseline_context);
- virtual ~RequestContext();
-
- // Set the user agent for requests using this context. The default is
- // the browser's UA string.
- void set_user_agent(const std::string& ua) { user_agent_ = ua; }
- bool is_user_agent_set() const { return !user_agent_.empty(); }
-
- virtual const std::string& GetUserAgent(const GURL& url) const {
- // If the user agent is set explicitly return that, otherwise call the
- // base class method to return default value.
- return user_agent_.empty() ?
- URLRequestContext::GetUserAgent(url) : user_agent_;
- }
-
- private:
- std::string user_agent_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestContext);
- };
-
- HttpBridge(RequestContext* context, MessageLoop* io_loop);
- virtual ~HttpBridge();
-
- // sync_api::HttpPostProvider implementation.
- virtual void SetUserAgent(const char* user_agent);
- virtual void SetURL(const char* url, int port);
- virtual void SetPostPayload(const char* content_type, int content_length,
- const char* content);
- virtual void AddCookieForRequest(const char* cookie);
- virtual bool MakeSynchronousPost(int* os_error_code, int* response_code);
- virtual int GetResponseContentLength() const;
- virtual const char* GetResponseContent() const;
- virtual int GetResponseCookieCount() const;
- virtual const char* GetResponseCookieAt(int cookie_number) const;
-
- // URLFetcher::Delegate implementation.
- virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url,
- const URLRequestStatus& status,
- int response_code,
- const ResponseCookies& cookies,
- const std::string& data);
-
- protected:
- // Protected virtual so the unit test can override to shunt network requests.
- virtual void MakeAsynchronousPost();
-
- private:
- friend class ::HttpBridgeTest;
-
- // Called on the io_loop_ to issue the network request. The extra level
- // of indirection is so that the unit test can override this behavior but we
- // still have a function to statically pass to PostTask.
- void CallMakeAsynchronousPost() { MakeAsynchronousPost(); }
-
- // A customized URLRequestContext for bridged requests. See RequestContext
- // definition for details.
- RequestContext* context_for_request_;
-
- // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO LOOP,
- // so we can block created_on_loop_ while the fetch is in progress.
- // NOTE: This is not a scoped_ptr for a reason. It must be deleted on the same
- // thread that created it, which isn't the same thread |this| gets deleted on.
- // We must manually delete url_poster_ on the io_loop_.
- URLFetcher* url_poster_;
-
- // The message loop of the thread we were created on. This is the thread that
- // will block on MakeSynchronousPost while the IO thread fetches data from
- // the network.
- // This should be the main syncer thread (SyncerThread) which is what blocks
- // on network IO through curl_easy_perform.
- MessageLoop* const created_on_loop_;
-
- // Member variable for the IO loop instead of asking ChromeThread directly,
- // done this way for testability.
- MessageLoop* const io_loop_;
-
- // The URL to POST to.
- GURL url_for_request_;
-
- // POST payload information.
- std::string content_type_;
- std::string request_content_;
-
- // Cached response data.
- bool request_completed_;
- bool request_succeeded_;
- int http_response_code_;
- int os_error_code_;
- ResponseCookies response_cookies_;
- std::string response_content_;
-
- // A waitable event we use to provide blocking semantics to
- // MakeSynchronousPost. We block created_on_loop_ while the io_loop_ fetches
- // network request.
- base::WaitableEvent http_post_completed_;
-
- // This is here so that the unit test subclass can force our URLFetcher to
- // use the io_loop_ passed on construction for network requests, rather than
- // ChromeThread::IO's message loop (which won't exist in testing).
- bool use_io_loop_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpBridge);
-};
-
-class HttpBridgeFactory
- : public sync_api::HttpPostProviderFactory {
- public:
- HttpBridgeFactory() : request_context_(NULL) { }
- virtual ~HttpBridgeFactory();
- virtual sync_api::HttpPostProviderInterface* Create();
- virtual void Destroy(sync_api::HttpPostProviderInterface* http);
- private:
- HttpBridge::RequestContext* GetRequestContext();
- // We must Release() this from the IO thread.
- HttpBridge::RequestContext* request_context_;
- DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/http_bridge_unittest.cc b/chrome/browser/sync/glue/http_bridge_unittest.cc
deleted file mode 100644
index 4dd9a9b..0000000
--- a/chrome/browser/sync/glue/http_bridge_unittest.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2006-2008 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.
-#ifdef CHROME_PERSONALIZATION
-
-#include "base/thread.h"
-#include "chrome/browser/sync/glue/http_bridge.h"
-#include "net/url_request/url_request_unittest.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using browser_sync::HttpBridge;
-
-namespace {
-// TODO(timsteele): Should use PathService here. See Chromium Issue 3113.
-const char16 kDocRoot[] = L"chrome/test/data";
-}
-
-class HttpBridgeTest : public testing::Test {
- public:
- HttpBridgeTest() : io_thread_("HttpBridgeTest IO thread") {
- }
-
- virtual void SetUp() {
- base::Thread::Options options;
- options.message_loop_type = MessageLoop::TYPE_IO;
- io_thread_.StartWithOptions(options);
- }
-
- virtual void TearDown() {
- io_thread_.Stop();
- }
-
- HttpBridge* BuildBridge() {
- if (!request_context_) {
- request_context_ = new HttpBridge::RequestContext(
- new TestURLRequestContext());
- }
- HttpBridge* bridge = new HttpBridge(request_context_,
- io_thread_.message_loop());
- bridge->use_io_loop_for_testing_ = true;
- return bridge;
- }
-
- MessageLoop* io_thread_loop() { return io_thread_.message_loop(); }
- private:
- // Separate thread for IO used by the HttpBridge.
- scoped_refptr<HttpBridge::RequestContext> request_context_;
- base::Thread io_thread_;
-};
-
-// An HttpBridge that doesn't actually make network requests and just calls
-// back with dummy response info.
-class ShuntedHttpBridge : public HttpBridge {
- public:
- ShuntedHttpBridge(const URLRequestContext* baseline_context,
- MessageLoop* io_loop, HttpBridgeTest* test)
- : HttpBridge(new HttpBridge::RequestContext(baseline_context),
- io_loop), test_(test) { }
- protected:
- virtual void MakeAsynchronousPost() {
- ASSERT_TRUE(MessageLoop::current() == test_->io_thread_loop());
- // We don't actually want to make a request for this test, so just callback
- // as if it completed.
- test_->io_thread_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &ShuntedHttpBridge::CallOnURLFetchComplete));
- }
- private:
- void CallOnURLFetchComplete() {
- ASSERT_TRUE(MessageLoop::current() == test_->io_thread_loop());
- // We return one cookie and a dummy content response.
- ResponseCookies cookies;
- cookies.push_back("cookie1");
- std::string response_content = "success!";
- OnURLFetchComplete(NULL, GURL("www.google.com"), URLRequestStatus(),
- 200, cookies, response_content);
- }
- HttpBridgeTest* test_;
-};
-
-// Test the HttpBridge without actually making any network requests.
-TEST_F(HttpBridgeTest, TestMakeSynchronousPostShunted) {
- scoped_refptr<HttpBridge> http_bridge(new ShuntedHttpBridge(
- new TestURLRequestContext(), io_thread_loop(), this));
- http_bridge->SetUserAgent("bob");
- http_bridge->SetURL("http://www.google.com", 9999);
- http_bridge->SetPostPayload("text/plain", 2, " ");
-
- int os_error = 0;
- int response_code = 0;
- bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
- EXPECT_TRUE(success);
- EXPECT_EQ(200, response_code);
- EXPECT_EQ(0, os_error);
- EXPECT_EQ(1, http_bridge->GetResponseCookieCount());
- // TODO(timsteele): This is a valid test condition, it's just temporarily
- // broken so that HttpBridge satisfies the ServerConnectionManager.
-#if FIXED_SYNC_BACKEND_COOKIE_PARSING
- EXPECT_EQ(std::string("cookie1"),
- std::string(http_bridge->GetResponseCookieAt(0)));
-#endif
- EXPECT_EQ(8, http_bridge->GetResponseContentLength());
- EXPECT_EQ(std::string("success!"),
- std::string(http_bridge->GetResponseContent()));
-}
-
-// Full round-trip test of the HttpBridge, using default UA string and
-// no request cookies.
-TEST_F(HttpBridgeTest, TestMakeSynchronousPostLiveWithPayload) {
- scoped_refptr<HTTPTestServer> server = HTTPTestServer::CreateServer(kDocRoot,
- NULL);
- ASSERT_TRUE(NULL != server.get());
-
- scoped_refptr<HttpBridge> http_bridge(BuildBridge());
-
- std::string payload = "this should be echoed back";
- GURL echo = server->TestServerPage("echo");
- http_bridge->SetURL(echo.spec().c_str(), echo.IntPort());
- http_bridge->SetPostPayload("application/x-www-form-urlencoded",
- payload.length() + 1, payload.c_str());
- int os_error = 0;
- int response_code = 0;
- bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
- EXPECT_TRUE(success);
- EXPECT_EQ(200, response_code);
- EXPECT_EQ(0, os_error);
- EXPECT_EQ(0, http_bridge->GetResponseCookieCount());
- EXPECT_EQ(payload.length() + 1, http_bridge->GetResponseContentLength());
- EXPECT_EQ(payload, std::string(http_bridge->GetResponseContent()));
-}
-
-// Full round-trip test of the HttpBridge, using custom UA string and
-// multiple request cookies.
-TEST_F(HttpBridgeTest, TestMakeSynchronousPostLiveComprehensive) {
- scoped_refptr<HTTPTestServer> server = HTTPTestServer::CreateServer(kDocRoot,
- NULL);
- ASSERT_TRUE(NULL != server.get());
- scoped_refptr<HttpBridge> http_bridge(BuildBridge());
-
- GURL echo_header = server->TestServerPage("echoall");
- http_bridge->SetUserAgent("bob");
- http_bridge->SetURL(echo_header.spec().c_str(), echo_header.IntPort());
- http_bridge->AddCookieForRequest("foo=bar");
- http_bridge->AddCookieForRequest("baz=boo");
- std::string test_payload = "###TEST PAYLOAD###";
- http_bridge->SetPostPayload("text/html", test_payload.length() + 1,
- test_payload.c_str());
-
- int os_error = 0;
- int response_code = 0;
- bool success = http_bridge->MakeSynchronousPost(&os_error, &response_code);
- EXPECT_TRUE(success);
- EXPECT_EQ(200, response_code);
- EXPECT_EQ(0, os_error);
- EXPECT_EQ(0, http_bridge->GetResponseCookieCount());
- std::string response = http_bridge->GetResponseContent();
-// TODO(timsteele): This is a valid test condition, it's just temporarily
-// broken so that HttpBridge satisfies the ServerConnectionManager; the format
-// seems to be surprising the TestServer, because it isn't echoing the headers
-// properly.
-#if FIXED_SYNCER_BACKEND_COOKIE_PARSING
- EXPECT_NE(std::string::npos, response.find("Cookie: foo=bar; baz=boo"));
- EXPECT_NE(std::string::npos, response.find("User-Agent: bob"));
-#endif
- EXPECT_NE(std::string::npos, response.find(test_payload.c_str()));
-}
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/model_associator.cc b/chrome/browser/sync/glue/model_associator.cc
deleted file mode 100644
index 3d73612..0000000
--- a/chrome/browser/sync/glue/model_associator.cc
+++ /dev/null
@@ -1,504 +0,0 @@
-// Copyright (c) 2006-2009 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "chrome/browser/sync/glue/model_associator.h"
-
-#include <stack>
-
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-
-namespace browser_sync {
-
-// The sync protocol identifies top-level entities by means of well-known tags,
-// which should not be confused with titles. Each tag corresponds to a
-// singleton instance of a particular top-level node in a user's share; the
-// tags are consistent across users. The tags allow us to locate the specific
-// folders whose contents we care about synchronizing, without having to do a
-// lookup by name or path. The tags should not be made user-visible.
-// For example, the tag "bookmark_bar" represents the permanent node for
-// bookmarks bar in Chrome. The tag "other_bookmarks" represents the permanent
-// folder Other Bookmarks in Chrome.
-//
-// It is the responsibility of something upstream (at time of writing,
-// the sync server) to create these tagged nodes when initializing sync
-// for the first time for a user. Thus, once the backend finishes
-// initializing, the ProfileSyncService can rely on the presence of tagged
-// nodes.
-//
-// TODO(ncarter): Pull these tags from an external protocol specification
-// rather than hardcoding them here.
-static const wchar_t* kOtherBookmarksTag = L"other_bookmarks";
-static const wchar_t* kBookmarkBarTag = L"bookmark_bar";
-
-// Bookmark comparer for map of bookmark nodes.
-class BookmarkComparer {
- public:
- // Compares the two given nodes and returns whether node1 should appear
- // before node2 in strict weak ordering.
- bool operator()(const BookmarkNode* node1,
- const BookmarkNode* node2) const {
- DCHECK(node1);
- DCHECK(node2);
-
- // Keep folder nodes before non-folder nodes.
- if (node1->is_folder() != node2->is_folder())
- return node1->is_folder();
-
- int result = node1->GetTitle().compare(node2->GetTitle());
- if (result != 0)
- return result < 0;
-
- result = node1->GetURL().spec().compare(node2->GetURL().spec());
- if (result != 0)
- return result < 0;
-
- return false;
- }
-};
-
-// Provides the following abstraction: given a parent bookmark node, find best
-// matching child node for many sync nodes.
-class BookmarkNodeFinder {
- public:
- // Creats an instance with the given parent bookmark node.
- explicit BookmarkNodeFinder(const BookmarkNode* parent_node);
-
- // Finds best matching node for the given sync node.
- // Returns the matching node if one exists; NULL otherwise. If a matching
- // node is found, it's removed for further matches.
- const BookmarkNode* FindBookmarkNode(const sync_api::BaseNode& sync_node);
-
- private:
- typedef std::set<const BookmarkNode*, BookmarkComparer> BookmarkNodesSet;
-
- const BookmarkNode* parent_node_;
- BookmarkNodesSet child_nodes_;
-
- DISALLOW_COPY_AND_ASSIGN(BookmarkNodeFinder);
-};
-
-BookmarkNodeFinder::BookmarkNodeFinder(const BookmarkNode* parent_node)
- : parent_node_(parent_node) {
- for (int i = 0; i < parent_node_->GetChildCount(); ++i)
- child_nodes_.insert(parent_node_->GetChild(i));
-}
-
-const BookmarkNode* BookmarkNodeFinder::FindBookmarkNode(
- const sync_api::BaseNode& sync_node) {
- // Create a bookmark node from the given sync node.
- BookmarkNode temp_node(GURL(sync_node.GetURL()));
- temp_node.SetTitle(UTF16ToWide(sync_node.GetTitle()));
- if (sync_node.GetIsFolder())
- temp_node.SetType(BookmarkNode::FOLDER);
- else
- temp_node.SetType(BookmarkNode::URL);
-
- const BookmarkNode* result = NULL;
- BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node);
- if (iter != child_nodes_.end()) {
- result = *iter;
- // Remove the matched node so we don't match with it again.
- child_nodes_.erase(iter);
- }
-
- return result;
-}
-
-ModelAssociator::ModelAssociator(ProfileSyncService* sync_service)
- : sync_service_(sync_service),
- task_pending_(false) {
- DCHECK(sync_service_);
-}
-
-void ModelAssociator::ClearAll() {
- id_map_.clear();
- id_map_inverse_.clear();
- dirty_assocations_sync_ids_.clear();
-}
-
-int64 ModelAssociator::GetSyncIdFromBookmarkId(int64 node_id) const {
- BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id);
- return iter == id_map_.end() ? sync_api::kInvalidId : iter->second;
-}
-
-bool ModelAssociator::GetBookmarkIdFromSyncId(int64 sync_id,
- int64* node_id) const {
- SyncIdToBookmarkIdMap::const_iterator iter = id_map_inverse_.find(sync_id);
- if (iter == id_map_inverse_.end())
- return false;
- *node_id = iter->second;
- return true;
-}
-
-bool ModelAssociator::InitSyncNodeFromBookmarkId(
- int64 node_id,
- sync_api::BaseNode* sync_node) {
- DCHECK(sync_node);
- int64 sync_id = GetSyncIdFromBookmarkId(node_id);
- if (sync_id == sync_api::kInvalidId)
- return false;
- if (!sync_node->InitByIdLookup(sync_id))
- return false;
- DCHECK(sync_node->GetId() == sync_id);
- return true;
-}
-
-const BookmarkNode* ModelAssociator::GetBookmarkNodeFromSyncId(int64 sync_id) {
- int64 node_id;
- if (!GetBookmarkIdFromSyncId(sync_id, &node_id))
- return false;
- BookmarkModel* model = sync_service_->profile()->GetBookmarkModel();
- return model->GetNodeByID(node_id);
-}
-
-void ModelAssociator::AssociateIds(int64 node_id, int64 sync_id) {
- DCHECK_NE(sync_id, sync_api::kInvalidId);
- DCHECK(id_map_.find(node_id) == id_map_.end());
- DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end());
- id_map_[node_id] = sync_id;
- id_map_inverse_[sync_id] = node_id;
- dirty_assocations_sync_ids_.insert(sync_id);
- PostPersistAssociationsTask();
-}
-
-void ModelAssociator::DisassociateIds(int64 sync_id) {
- SyncIdToBookmarkIdMap::iterator iter = id_map_inverse_.find(sync_id);
- if (iter == id_map_inverse_.end())
- return;
- id_map_.erase(iter->second);
- id_map_inverse_.erase(iter);
- dirty_assocations_sync_ids_.erase(sync_id);
-}
-
-bool ModelAssociator::BookmarkModelHasUserCreatedNodes() const {
- BookmarkModel* model = sync_service_->profile()->GetBookmarkModel();
- DCHECK(model->IsLoaded());
- return model->GetBookmarkBarNode()->GetChildCount() > 0 ||
- model->other_node()->GetChildCount() > 0;
-}
-
-bool ModelAssociator::SyncModelHasUserCreatedNodes() {
- int64 bookmark_bar_sync_id;
- if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag),
- &bookmark_bar_sync_id)) {
- NOTREACHED();
- return false;
- }
- int64 other_bookmarks_sync_id;
- if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag),
- &other_bookmarks_sync_id)) {
- NOTREACHED();
- return false;
- }
-
- sync_api::ReadTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
-
- sync_api::ReadNode bookmark_bar_node(&trans);
- if (!bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id)) {
- NOTREACHED();
- return false;
- }
-
- sync_api::ReadNode other_bookmarks_node(&trans);
- if (!other_bookmarks_node.InitByIdLookup(other_bookmarks_sync_id)) {
- NOTREACHED();
- return false;
- }
-
- // Sync model has user created nodes if either one of the permanent nodes
- // has children.
- return bookmark_bar_node.GetFirstChildId() != sync_api::kInvalidId ||
- other_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId;
-}
-
-bool ModelAssociator::NodesMatch(const BookmarkNode* bookmark,
- const sync_api::BaseNode* sync_node) const {
- if (bookmark->GetTitle() != UTF16ToWide(sync_node->GetTitle()))
- return false;
- if (bookmark->is_folder() != sync_node->GetIsFolder())
- return false;
- if (bookmark->is_url()) {
- if (bookmark->GetURL() != GURL(sync_node->GetURL()))
- return false;
- }
- // Don't compare favicons here, because they are not really
- // user-updated and we don't have versioning information -- a site changing
- // its favicon shouldn't result in a bookmark mismatch.
- return true;
-}
-
-bool ModelAssociator::AssociateTaggedPermanentNode(
- const BookmarkNode* permanent_node,
- const string16 &tag) {
- // Do nothing if |permanent_node| is already initialized and associated.
- int64 sync_id = GetSyncIdFromBookmarkId(permanent_node->id());
- if (sync_id != sync_api::kInvalidId)
- return true;
- if (!GetSyncIdForTaggedNode(tag, &sync_id))
- return false;
-
- AssociateIds(permanent_node->id(), sync_id);
- return true;
-}
-
-bool ModelAssociator::GetSyncIdForTaggedNode(const string16& tag,
- int64* sync_id) {
- sync_api::ReadTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
- sync_api::ReadNode sync_node(&trans);
- if (!sync_node.InitByTagLookup(tag.c_str()))
- return false;
- *sync_id = sync_node.GetId();
- return true;
-}
-
-bool ModelAssociator::AssociateModels() {
- // Try to load model associations from persisted associations first. If that
- // succeeds, we don't need to run the complex model matching algorithm.
- if (LoadAssociations())
- return true;
-
- ClearAll();
-
- // We couldn't load model assocations from persisted assocations. So build
- // them.
- return BuildAssocations();
-}
-
-bool ModelAssociator::BuildAssocations() {
- // Algorithm description:
- // Match up the roots and recursively do the following:
- // * For each sync node for the current sync parent node, find the best
- // matching bookmark node under the corresponding bookmark parent node.
- // If no matching node is found, create a new bookmark node in the same
- // position as the corresponding sync node.
- // If a matching node is found, update the properties of it from the
- // corresponding sync node.
- // * When all children sync nodes are done, add the extra children bookmark
- // nodes to the sync parent node.
- //
- // This algorithm will do a good job of merging when folder names are a good
- // indicator of the two folders being the same. It will handle reordering and
- // new node addition very well (without creating duplicates).
- // This algorithm will not do well if the folder name has changes but the
- // children under them are all the same.
-
- BookmarkModel* model = sync_service_->profile()->GetBookmarkModel();
- DCHECK(model->IsLoaded());
-
- // To prime our association, we associate the top-level nodes, Bookmark Bar
- // and Other Bookmarks.
- if (!AssociateTaggedPermanentNode(model->other_node(),
- WideToUTF16(kOtherBookmarksTag))) {
- NOTREACHED() << "Server did not create top-level nodes. Possibly we "
- << "are running against an out-of-date server?";
- return false;
- }
- if (!AssociateTaggedPermanentNode(model->GetBookmarkBarNode(),
- WideToUTF16(kBookmarkBarTag))) {
- NOTREACHED() << "Server did not create top-level nodes. Possibly we "
- << "are running against an out-of-date server?";
- return false;
- }
- int64 bookmark_bar_sync_id = GetSyncIdFromBookmarkId(
- model->GetBookmarkBarNode()->id());
- DCHECK(bookmark_bar_sync_id != sync_api::kInvalidId);
- int64 other_bookmarks_sync_id = GetSyncIdFromBookmarkId(
- model->other_node()->id());
- DCHECK(other_bookmarks_sync_id!= sync_api::kInvalidId);
-
- std::stack<int64> dfs_stack;
- dfs_stack.push(other_bookmarks_sync_id);
- dfs_stack.push(bookmark_bar_sync_id);
-
- sync_api::WriteTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
-
- while (!dfs_stack.empty()) {
- int64 sync_parent_id = dfs_stack.top();
- dfs_stack.pop();
-
- sync_api::ReadNode sync_parent(&trans);
- if (!sync_parent.InitByIdLookup(sync_parent_id)) {
- NOTREACHED();
- return false;
- }
- // Only folder nodes are pushed on to the stack.
- DCHECK(sync_parent.GetIsFolder());
-
- const BookmarkNode* parent_node = GetBookmarkNodeFromSyncId(sync_parent_id);
- DCHECK(parent_node->is_folder());
-
- BookmarkNodeFinder node_finder(parent_node);
-
- int index = 0;
- int64 sync_child_id = sync_parent.GetFirstChildId();
- while (sync_child_id != sync_api::kInvalidId) {
- sync_api::WriteNode sync_child_node(&trans);
- if (!sync_child_node.InitByIdLookup(sync_child_id)) {
- NOTREACHED();
- return false;
- }
-
- const BookmarkNode* child_node = NULL;
- child_node = node_finder.FindBookmarkNode(sync_child_node);
- if (child_node) {
- model->Move(child_node, parent_node, index);
- // Set the favicon for bookmark node from sync node or vice versa.
- if (!sync_service_->SetBookmarkFavicon(&sync_child_node, child_node))
- sync_service_->SetSyncNodeFavicon(child_node, &sync_child_node);
- } else {
- // Create a new bookmark node for the sync node.
- child_node = sync_service_->CreateBookmarkNode(&sync_child_node,
- parent_node,
- index);
- }
- AssociateIds(child_node->id(), sync_child_id);
- if (sync_child_node.GetIsFolder())
- dfs_stack.push(sync_child_id);
-
- sync_child_id = sync_child_node.GetSuccessorId();
- ++index;
- }
-
- // At this point all the children nodes of the parent sync node have
- // corresponding children in the parent bookmark node and they are all in
- // the right positions: from 0 to index - 1.
- // So the children starting from index in the parent bookmark node are the
- // ones that are not present in the parent sync node. So create them.
- for (int i = index; i < parent_node->GetChildCount(); ++i) {
- sync_child_id = sync_service_->CreateSyncNode(parent_node, i, &trans);
- if (parent_node->GetChild(i)->is_folder())
- dfs_stack.push(sync_child_id);
- }
- }
- return true;
-}
-
-void ModelAssociator::PostPersistAssociationsTask() {
- // No need to post a task if a task is already pending.
- if (task_pending_)
- return;
- task_pending_ = true;
- MessageLoop::current()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ModelAssociator::PersistAssociations));
-}
-
-void ModelAssociator::PersistAssociations() {
- DCHECK(task_pending_);
- task_pending_ = false;
-
- // If there are no dirty assocations we have nothing to do. We handle this
- // explicity instead of letting the for loop do it to avoid creating a write
- // transaction in this case.
- if (dirty_assocations_sync_ids_.empty()) {
- DCHECK(id_map_.empty());
- DCHECK(id_map_inverse_.empty());
- return;
- }
-
- sync_api::WriteTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
- DirtyAssocationsSyncIds::iterator iter;
- for (iter = dirty_assocations_sync_ids_.begin();
- iter != dirty_assocations_sync_ids_.end();
- ++iter) {
- int64 sync_id = *iter;
- sync_api::WriteNode sync_node(&trans);
- if (!sync_node.InitByIdLookup(sync_id)) {
- sync_service_->SetUnrecoverableError();
- return;
- }
- int64 node_id;
- if (GetBookmarkIdFromSyncId(sync_id, &node_id))
- sync_node.SetExternalId(node_id);
- else
- NOTREACHED();
- }
- dirty_assocations_sync_ids_.clear();
-}
-
-bool ModelAssociator::LoadAssociations() {
- BookmarkModel* model = sync_service_->profile()->GetBookmarkModel();
- DCHECK(model->IsLoaded());
- // If the bookmarks changed externally, our previous assocations may not be
- // valid; so return false.
- if (model->file_changed())
- return false;
-
- // Our persisted assocations should be valid. Try to populate id assocation
- // maps using persisted assocations.
-
- int64 other_bookmarks_id;
- if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag),
- &other_bookmarks_id)) {
- NOTREACHED(); // We should always be able to find the permanent nodes.
- return false;
- }
- int64 bookmark_bar_id;
- if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag), &bookmark_bar_id)) {
- NOTREACHED(); // We should always be able to find the permanent nodes.
- return false;
- }
-
- std::stack<int64> dfs_stack;
- dfs_stack.push(other_bookmarks_id);
- dfs_stack.push(bookmark_bar_id);
-
- sync_api::ReadTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
-
- while (!dfs_stack.empty()) {
- int64 parent_id = dfs_stack.top();
- dfs_stack.pop();
- sync_api::ReadNode sync_parent(&trans);
- if (!sync_parent.InitByIdLookup(parent_id)) {
- NOTREACHED();
- return false;
- }
-
- int64 external_id = sync_parent.GetExternalId();
- if (external_id == 0)
- return false;
-
- const BookmarkNode* node = model->GetNodeByID(external_id);
- if (!node)
- return false;
-
- // Don't try to call NodesMatch on permanent nodes like bookmark bar and
- // other bookmarks. They are not expected to match.
- if (node != model->GetBookmarkBarNode() &&
- node != model->other_node() &&
- !NodesMatch(node, &sync_parent))
- return false;
-
- AssociateIds(external_id, sync_parent.GetId());
-
- // Add all children of the current node to the stack.
- int64 child_id = sync_parent.GetFirstChildId();
- while (child_id != sync_api::kInvalidId) {
- dfs_stack.push(child_id);
- sync_api::ReadNode child_node(&trans);
- if (!child_node.InitByIdLookup(child_id)) {
- NOTREACHED();
- return false;
- }
- child_id = child_node.GetSuccessorId();
- }
- }
- DCHECK(dfs_stack.empty());
- return true;
-}
-
-} // namespace browser_sync
-
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/glue/model_associator.h b/chrome/browser/sync/glue/model_associator.h
deleted file mode 100644
index a81f337..0000000
--- a/chrome/browser/sync/glue/model_associator.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2006-2009 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCATOR_H_
-#define CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCATOR_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "base/string16.h"
-
-class BookmarkNode;
-
-namespace sync_api {
-class BaseNode;
-class BaseTransaction;
-class ReadNode;
-};
-
-class ProfileSyncService;
-
-namespace browser_sync {
-
-// Contains all model assocation related logic:
-// * Algorithm to associate bookmark model and sync model.
-// * Methods to get a bookmark node for a given sync node and vice versa.
-// * Persisting model assocations and loading them back.
-class ModelAssociator
- : public base::RefCountedThreadSafe<ModelAssociator> {
- public:
- explicit ModelAssociator(ProfileSyncService* sync_service);
- virtual ~ModelAssociator() { }
-
- // Clears all assocations .
- void ClearAll();
-
- // Returns sync id for the given bookmark node id.
- // Returns sync_api::kInvalidId if the sync node is not found for the given
- // bookmark node id.
- int64 GetSyncIdFromBookmarkId(int64 node_id) const;
-
- // Stores bookmark node id for the given sync id in bookmark_id. Returns true
- // if the bookmark id was successfully found; false otherwise.
- bool GetBookmarkIdFromSyncId(int64 sync_id, int64* bookmark_id) const;
-
- // Initializes the given sync node from the given bookmark node id.
- // Returns false if no sync node was found for the given bookmark node id or
- // if the initialization of sync node fails.
- bool InitSyncNodeFromBookmarkId(int64 node_id, sync_api::BaseNode* sync_node);
-
- // Returns the bookmark node for the given sync id.
- // Returns NULL if no bookmark node is found for the given sync id.
- const BookmarkNode* GetBookmarkNodeFromSyncId(int64 sync_id);
-
- // Associates the given bookmark node id with the given sync id.
- void AssociateIds(int64 node_id, int64 sync_id);
- // Disassociate the ids that correspond to the given sync id.
- void DisassociateIds(int64 sync_id);
-
- // Returns whether the bookmark model has user created nodes or not. That is,
- // whether there are nodes in the bookmark model except the bookmark bar and
- // other bookmarks.
- bool BookmarkModelHasUserCreatedNodes() const;
-
- // Returns whether the sync model has nodes other than the permanent tagged
- // nodes.
- bool SyncModelHasUserCreatedNodes();
-
- // AssociateModels iterates through both the sync and the browser
- // bookmark model, looking for matched pairs of items. For any pairs it
- // finds, it will call AssociateSyncID. For any unmatched items,
- // MergeAndAssociateModels will try to repair the match, e.g. by adding a new
- // node. After successful completion, the models should be identical and
- // corresponding. Returns true on success. On failure of this step, we
- // should abort the sync operation and report an error to the user.
- bool AssociateModels();
-
- protected:
- // Stores the id of the node with the given tag in |sync_id|.
- // Returns of that node was found successfully.
- // Tests override this.
- virtual bool GetSyncIdForTaggedNode(const string16& tag, int64* sync_id);
-
- // Returns sync service instance.
- ProfileSyncService* sync_service() { return sync_service_; }
-
- private:
- typedef std::map<int64, int64> BookmarkIdToSyncIdMap;
- typedef std::map<int64, int64> SyncIdToBookmarkIdMap;
- typedef std::set<int64> DirtyAssocationsSyncIds;
-
- // Posts a task to persist dirty assocations.
- void PostPersistAssociationsTask();
- // Persists all dirty assocations.
- void PersistAssociations();
-
- // Loads the persisted assocations into in-memory maps.
- // If the persisted associations are out-of-date due to some reason, returns
- // false; otehrwise returns true.
- bool LoadAssociations();
-
- // Matches up the bookmark model and the sync model to build model
- // assocations.
- bool BuildAssocations();
-
- // Associate a top-level node of the bookmark model with a permanent node in
- // the sync domain. Such permanent nodes are identified by a tag that is
- // well known to the server and the client, and is unique within a particular
- // user's share. For example, "other_bookmarks" is the tag for the Other
- // Bookmarks folder. The sync nodes are server-created.
- bool AssociateTaggedPermanentNode(const BookmarkNode* permanent_node,
- const string16& tag);
-
- // Compare the properties of a pair of nodes from either domain.
- bool NodesMatch(const BookmarkNode* bookmark,
- const sync_api::BaseNode* sync_node) const;
-
- ProfileSyncService* sync_service_;
- BookmarkIdToSyncIdMap id_map_;
- SyncIdToBookmarkIdMap id_map_inverse_;
- // Stores sync ids for dirty associations.
- DirtyAssocationsSyncIds dirty_assocations_sync_ids_;
-
- // Indicates whether there is already a pending task to persist dirty model
- // associations.
- bool task_pending_;
-
- DISALLOW_COPY_AND_ASSIGN(ModelAssociator);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCATOR_H_
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
deleted file mode 100644
index 4614ee3..0000000
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "base/file_version_info.h"
-#include "base/file_util.h"
-#include "base/string_util.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/glue/http_bridge.h"
-#include "chrome/browser/sync/glue/bookmark_model_worker.h"
-#include "webkit/glue/webkit_glue.h"
-
-static const char kSwitchSyncServiceURL[] = "sync-url";
-static const char kSwitchSyncServicePort[] = "sync-port";
-static const int kSaveChangesIntervalSeconds = 10;
-static const char kGaiaServiceId[] = "chromiumsync";
-static const char kGaiaSourceForChrome[] = "ChromiumBrowser";
-static const FilePath::CharType kSyncDataFolderName[] =
- FILE_PATH_LITERAL("Sync Data");
-
-namespace browser_sync {
-
-SyncBackendHost::SyncBackendHost(SyncFrontend* frontend,
- const FilePath& profile_path)
- : core_thread_("Chrome_SyncCoreThread"),
- frontend_loop_(MessageLoop::current()),
- bookmark_model_worker_(NULL),
- frontend_(frontend),
- sync_data_folder_path_(profile_path.Append(kSyncDataFolderName)),
- last_auth_error_(AUTH_ERROR_NONE) {
- core_ = new Core(this);
-}
-
-SyncBackendHost::~SyncBackendHost() {
- DCHECK(!core_ && !frontend_) << "Must call Shutdown before destructor.";
-}
-
-void SyncBackendHost::Initialize(const GURL& sync_service_url) {
- if (!core_thread_.Start())
- return;
-
- bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_);
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoInitialize,
- sync_service_url, bookmark_model_worker_, true));
-}
-
-void SyncBackendHost::Authenticate(const std::string& username,
- const std::string& password) {
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoAuthenticate,
- username, password));
-}
-
-void SyncBackendHost::Shutdown(bool sync_disabled) {
- // Thread shutdown should occur in the following order:
- // - SyncerThread
- // - CoreThread
- // - UI Thread (stops some time after we return from this call).
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(),
- &SyncBackendHost::Core::DoShutdown,
- sync_disabled));
-
- // Before joining the core_thread_, we wait for the BookmarkModelWorker to
- // give us the green light that it is not depending on the frontend_loop_ to
- // process any more tasks. Stop() blocks until this termination condition
- // is true.
- bookmark_model_worker_->Stop();
-
- // Stop will return once the thread exits, which will be after DoShutdown
- // runs. DoShutdown needs to run from core_thread_ because the sync backend
- // requires any thread that opened sqlite handles to relinquish them
- // personally. We need to join threads, because otherwise the main Chrome
- // thread (ui loop) can exit before DoShutdown finishes, at which point
- // virtually anything the sync backend does (or the post-back to
- // frontend_loop_ by our Core) will epically fail because the CRT won't be
- // initialized. For now this only ever happens at sync-enabled-Chrome exit,
- // meaning bug 1482548 applies to prolonged "waiting" that may occur in
- // DoShutdown.
- core_thread_.Stop();
-
- bookmark_model_worker_ = NULL;
- frontend_ = NULL;
- core_ = NULL; // Releases reference to core_.
-}
-
-void SyncBackendHost::Core::NotifyFrontend(FrontendNotification notification) {
- if (!host_ || !host_->frontend_) {
- return; // This can happen in testing because the UI loop processes tasks
- // after an instance of SyncBackendHost was destroyed. In real
- // life this doesn't happen.
- }
- switch(notification) {
- case INITIALIZED:
- host_->frontend_->OnBackendInitialized();
- return;
- case SYNC_CYCLE_COMPLETED:
- host_->frontend_->OnSyncCycleCompleted();
- return;
- }
-}
-
-SyncBackendHost::UserShareHandle SyncBackendHost::GetUserShareHandle() const {
- return core_->syncapi()->GetUserShare();
-}
-
-SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() {
- return core_->syncapi()->GetDetailedStatus();
-}
-
-SyncBackendHost::StatusSummary SyncBackendHost::GetStatusSummary() {
- return core_->syncapi()->GetStatusSummary();
-}
-
-string16 SyncBackendHost::GetAuthenticatedUsername() const {
- return UTF8ToUTF16(core_->syncapi()->GetAuthenticatedUsername());
-}
-
-AuthErrorState SyncBackendHost::GetAuthErrorState() const {
- return last_auth_error_;
-}
-
-SyncBackendHost::Core::Core(SyncBackendHost* backend)
- : host_(backend),
- syncapi_(new sync_api::SyncManager()) {
-}
-
-// Helper to construct a user agent string (ASCII) suitable for use by
-// the syncapi for any HTTP communication. This string is used by the sync
-// backend for classifying client types when calculating statistics.
-std::string MakeUserAgentForSyncapi() {
- std::string user_agent;
- user_agent = "Chrome ";
-#if defined (OS_WIN)
- user_agent += "WIN ";
-#elif defined (OS_LINUX)
- user_agent += "LINUX ";
-#elif defined (OS_MACOSX)
- user_agent += "MAC ";
-#endif
- scoped_ptr<FileVersionInfo> version_info(
- FileVersionInfo::CreateFileVersionInfoForCurrentModule());
- if (version_info == NULL) {
- DLOG(ERROR) << "Unable to create FileVersionInfo object";
- return user_agent;
- }
-
- user_agent += WideToASCII(version_info->product_version());
- user_agent += " (" + WideToASCII(version_info->last_change()) + ")";
- if (!version_info->is_official_build())
- user_agent += "-devel";
- return user_agent;
-}
-
-void SyncBackendHost::Core::DoInitialize(
- const GURL& service_url,
- BookmarkModelWorker* bookmark_model_worker,
- bool attempt_last_user_authentication) {
- DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
-
- // Make sure that the directory exists before initializing the backend.
- // If it already exists, this will do no harm.
- bool success = file_util::CreateDirectory(host_->sync_data_folder_path());
- DCHECK(success);
-
- syncapi_->SetObserver(this);
- string16 path_str;
-#if defined (OS_WIN)
- path_str = host_->sync_data_folder_path().value();
-#elif (defined (OS_LINUX) || defined (OS_MACOSX))
- path_str = UTF8ToUTF16(sync_data_folder_path().value());
-#endif
- success = syncapi_->Init(path_str.c_str(),
- (service_url.host() + service_url.path()).c_str(),
- service_url.EffectiveIntPort(),
- kGaiaServiceId,
- kGaiaSourceForChrome,
- service_url.SchemeIsSecure(),
- new HttpBridgeFactory(),
- new HttpBridgeFactory(),
- bookmark_model_worker,
- attempt_last_user_authentication,
- MakeUserAgentForSyncapi().c_str());
- DCHECK(success) << "Syncapi initialization failed!";
-}
-
-void SyncBackendHost::Core::DoAuthenticate(const std::string& username,
- const std::string& password) {
- DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
- syncapi_->Authenticate(username.c_str(), password.c_str());
-}
-
-void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
- DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
-
- save_changes_timer_.Stop();
- syncapi_->Shutdown(); // Stops the SyncerThread.
- syncapi_->RemoveObserver();
- host_->bookmark_model_worker_->OnSyncerShutdownComplete();
-
- if (sync_disabled &&
- file_util::DirectoryExists(host_->sync_data_folder_path())) {
- // Delete the sync data folder to cleanup backend data.
- bool success = file_util::Delete(host_->sync_data_folder_path(), true);
- DCHECK(success);
- }
-
- host_ = NULL;
-}
-
-static AuthErrorState AuthProblemToAuthError(
- const sync_api::SyncManager::AuthProblem& auth_problem) {
- switch(auth_problem) {
- case sync_api::SyncManager::AUTH_PROBLEM_NONE:
- return AUTH_ERROR_NONE;
- case sync_api::SyncManager::AUTH_PROBLEM_INVALID_GAIA_CREDENTIALS:
- return AUTH_ERROR_INVALID_GAIA_CREDENTIALS;
- case sync_api::SyncManager::AUTH_PROBLEM_CONNECTION_FAILED:
- return AUTH_ERROR_CONNECTION_FAILED;
- case sync_api::SyncManager::AUTH_PROBLEM_USER_NOT_SIGNED_UP:
- return AUTH_ERROR_USER_NOT_SIGNED_UP;
- }
-
- NOTREACHED() << "Unknown AuthProblem.";
- return AUTH_ERROR_NONE;
-}
-
-void SyncBackendHost::Core::OnChangesApplied(
- const sync_api::BaseTransaction* trans,
- const sync_api::SyncManager::ChangeRecord* changes,
- int change_count) {
- if (!host_ || !host_->frontend_) {
- DCHECK(false) << "OnChangesApplied called after Shutdown?";
- return;
- }
-
- // ChangesApplied is the one exception that should come over from the sync
- // backend already on the service_loop_ thanks to our BookmarkModelWorker.
- // SyncFrontend changes exclusively on the UI loop, because it updates
- // the bookmark model. As such, we don't need to worry about changes that
- // have been made to the bookmark model but not yet applied to the sync
- // model -- such changes only happen on the UI loop, and there's no
- // contention.
- if (host_->frontend_loop_ != MessageLoop::current()) {
- // TODO(ncarter): Bug 1480644. Make this a DCHECK once syncapi filters
- // out all irrelevant changes.
- DLOG(WARNING) << "Could not update bookmark model from non-UI thread";
- return;
- }
- host_->frontend_->ApplyModelChanges(trans, changes, change_count);
-}
-
-void SyncBackendHost::Core::OnSyncCycleCompleted() {
- host_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &Core::NotifyFrontend, SYNC_CYCLE_COMPLETED));
-}
-
-void SyncBackendHost::Core::OnInitializationComplete() {
- if (!host_ || !host_->frontend_)
- return; // We may have been told to Shutdown before initialization
- // completed.
-
- // We could be on some random sync backend thread, so MessageLoop::current()
- // can definitely be null in here.
- host_->frontend_loop_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &Core::NotifyFrontend, INITIALIZED));
-
- // Initialization is complete, so we can schedule recurring SaveChanges.
- host_->core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &Core::StartSavingChanges));
-}
-
-void SyncBackendHost::Core::OnAuthProblem(
- sync_api::SyncManager::AuthProblem auth_problem) {
- // We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
- // we can modify state.
- host_->frontend_loop_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &Core::HandleAuthErrorEventOnFrontendLoop,
- AuthProblemToAuthError(auth_problem)));
-}
-
-void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop(
- AuthErrorState new_auth_error) {
- if (!host_ || !host_->frontend_)
- return;
-
- DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
-
- host_->last_auth_error_ = new_auth_error;
- host_->frontend_->OnAuthError();
-}
-
-void SyncBackendHost::Core::StartSavingChanges() {
- save_changes_timer_.Start(
- base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
- this, &Core::SaveChanges);
-}
-
-void SyncBackendHost::Core::SaveChanges() {
- syncapi_->SaveChanges();
-}
-
-} // namespace browser_sync
-
-#endif
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
deleted file mode 100644
index eb89e43..0000000
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
-#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
-
-#include <string>
-
-#include "base/file_path.h"
-#include "base/lock.h"
-#include "base/message_loop.h"
-#include "base/ref_counted.h"
-#include "base/thread.h"
-#include "base/timer.h"
-#include "chrome/browser/sync/auth_error_state.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/bookmark_model_worker.h"
-#include "googleurl/src/gurl.h"
-
-namespace browser_sync {
-
-class SyncFrontend;
-
-// A UI-thread safe API into the sync backend that "hosts" the top-level
-// syncapi element, the SyncManager, on its own thread. This class handles
-// dispatch of potentially blocking calls to appropriate threads and ensures
-// that the SyncFrontend is only accessed on the UI loop.
-class SyncBackendHost {
- public:
- typedef sync_api::UserShare* UserShareHandle;
- typedef sync_api::SyncManager::Status::Summary StatusSummary;
- typedef sync_api::SyncManager::Status Status;
-
- // Create a SyncBackendHost with a reference to the |frontend| that it serves
- // and communicates to via the SyncFrontend interface (on the same thread
- // it used to call the constructor).
- SyncBackendHost(SyncFrontend* frontend, const FilePath& proifle_path);
- ~SyncBackendHost();
-
- // Called on |frontend_loop_| to kick off asynchronous initialization.
- void Initialize(const GURL& service_url);
-
- // Called on |frontend_loop_| to kick off asynchronous authentication.
- void Authenticate(const std::string& username, const std::string& password);
-
- // Called on |frontend_loop_| to kick off shutdown.
- // |sync_disabled| indicates if syncing is being disabled or not.
- // See the implementation and Core::DoShutdown for details.
- void Shutdown(bool sync_disabled);
-
- // Called on |frontend_loop_| to obtain a handle to the UserShare needed
- // for creating transactions.
- UserShareHandle GetUserShareHandle() const;
-
- // Called from any thread to obtain current status information in detailed or
- // summarized form.
- Status GetDetailedStatus();
- StatusSummary GetStatusSummary();
- AuthErrorState GetAuthErrorState() const;
-
- const FilePath& sync_data_folder_path() const {
- return sync_data_folder_path_;
- }
-
- // Returns the authenticated username of the sync user, or empty if none
- // exists. It will only exist if the authentication service provider (e.g
- // GAIA) has confirmed the username is authentic.
- string16 GetAuthenticatedUsername() const;
-
-#ifdef UNIT_TEST
- // Called from unit test to bypass authentication and initialize the syncapi
- // to a state suitable for testing but not production.
- void InitializeForTestMode(const std::wstring& test_user) {
- if (!core_thread_.Start())
- return;
- bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_);
- core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(),
- &SyncBackendHost::Core::DoInitializeForTest,
- bookmark_model_worker_,
- test_user));
- }
-#endif
-
- private:
- // The real guts of SyncBackendHost, to keep the public client API clean.
- class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
- public sync_api::SyncManager::Observer {
- public:
- explicit Core(SyncBackendHost* backend);
-
- // Note: This destructor should *always* be called from the thread that
- // created it, and *always* after core_thread_ has exited. The syncapi
- // watches thread exit events and keeps pointers to objects this dtor will
- // destroy, so this ordering is important.
- ~Core() {
- }
-
- // SyncManager::Observer implementation. The Core just acts like an air
- // traffic controller here, forwarding incoming messages to appropriate
- // landing threads.
- virtual void OnChangesApplied(
- const sync_api::BaseTransaction* trans,
- const sync_api::SyncManager::ChangeRecord* changes,
- int change_count);
- virtual void OnSyncCycleCompleted();
- virtual void OnInitializationComplete();
- virtual void OnAuthProblem(
- sync_api::SyncManager::AuthProblem auth_problem);
-
- // Note:
- //
- // The Do* methods are the various entry points from our SyncBackendHost.
- // It calls us on a dedicated thread to actually perform synchronous
- // (and potentially blocking) syncapi operations.
- //
- // Called on the SyncBackendHost core_thread_ to perform initialization
- // of the syncapi on behalf of SyncBackendHost::Initialize.
- void DoInitialize(const GURL& service_url,
- BookmarkModelWorker* bookmark_model_worker_,
- bool attempt_last_user_authentication);
-
- // Called on our SyncBackendHost's core_thread_ to perform authentication
- // on behalf of SyncBackendHost::Authenticate.
- void DoAuthenticate(const std::string& username,
- const std::string& password);
-
- // The shutdown order is a bit complicated:
- // 1) From |core_thread_|, invoke the syncapi Shutdown call to do a final
- // SaveChanges, close sqlite handles, and halt the syncer thread (which
- // could potentially block for 1 minute).
- // 2) Then, from |frontend_loop_|, halt the core_thread_. This causes
- // syncapi thread-exit handlers to run and make use of cached pointers to
- // various components owned implicitly by us.
- // 3) Destroy this Core. That will delete syncapi components in a safe order
- // because the thread that was using them has exited (in step 2).
- void DoShutdown(bool stopping_sync);
-
- sync_api::SyncManager* syncapi() { return syncapi_.get(); }
-
-#ifdef UNIT_TEST
- // Special form of initialization that does not try and authenticate the
- // last known user (since it will fail in test mode) and does some extra
- // setup to nudge the syncapi into a useable state.
- void DoInitializeForTest(BookmarkModelWorker* bookmark_model_worker,
- const std::wstring& test_user) {
- DoInitialize(GURL(), bookmark_model_worker, false);
- syncapi_->SetupForTestMode(WideToUTF16(test_user).c_str());
- }
-#endif
-
- private:
- // FrontendNotification defines parameters for NotifyFrontend. Each enum
- // value corresponds to the one SyncFrontend interface method that
- // NotifyFrontend should invoke.
- enum FrontendNotification {
- INITIALIZED, // OnBackendInitialized.
- SYNC_CYCLE_COMPLETED, // A round-trip sync-cycle took place and
- // the syncer has resolved any conflicts
- // that may have arisen.
- };
-
- // NotifyFrontend is how the Core communicates with the frontend across
- // threads. Having this extra method (rather than having the Core PostTask
- // to the frontend explicitly) means SyncFrontend implementations don't
- // need to be RefCountedThreadSafe because NotifyFrontend is invoked on the
- // |frontend_loop_|.
- void NotifyFrontend(FrontendNotification notification);
-
- // Invoked when initialization of syncapi is complete and we can start
- // our timer.
- // This must be called from the thread on which SaveChanges is intended to
- // be run on; the host's |core_thread_|.
- void StartSavingChanges();
-
- // Invoked periodically to tell the syncapi to persist its state
- // by writing to disk.
- // This is called from the thread we were created on (which is the
- // SyncBackendHost |core_thread_|), using a repeating timer that is kicked
- // off as soon as the SyncManager tells us it completed
- // initialization.
- void SaveChanges();
-
- // Dispatched to from HandleAuthErrorEventOnCoreLoop to handle updating
- // frontend UI components.
- void HandleAuthErrorEventOnFrontendLoop(AuthErrorState new_auth_error);
-
- // Our parent SyncBackendHost
- SyncBackendHost* host_;
-
- // The timer used to periodically call SaveChanges.
- base::RepeatingTimer<Core> save_changes_timer_;
-
- // The top-level syncapi entry point.
- scoped_ptr<sync_api::SyncManager> syncapi_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
- };
-
- // A thread we dedicate for use by our Core to perform initialization,
- // authentication, handle messages from the syncapi, and periodically tell
- // the syncapi to persist itself.
- base::Thread core_thread_;
-
- // Our core, which communicates directly to the syncapi.
- scoped_refptr<Core> core_;
-
- // A reference to the MessageLoop used to construct |this|, so we know how
- // to safely talk back to the SyncFrontend.
- MessageLoop* const frontend_loop_;
-
- // We hold on to the BookmarkModelWorker created for the syncapi to ensure
- // shutdown occurs in the sequence we expect by calling Stop() at the
- // appropriate time. It is guaranteed to be valid because the worker is
- // only destroyed when the SyncManager is destroyed, which happens when
- // our Core is destroyed, which happens in Shutdown().
- BookmarkModelWorker* bookmark_model_worker_;
-
- // The frontend which we serve (and are owned by).
- SyncFrontend* frontend_;
-
- // Path of the folder that stores the sync data files.
- FilePath sync_data_folder_path_;
-
- // UI-thread cache of the last AuthErrorState received from syncapi.
- AuthErrorState last_auth_error_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
-};
-
-// SyncFrontend is the interface used by SyncBackendHost to communicate with
-// the entity that created it and, presumably, is interested in sync-related
-// activity.
-// NOTE: All methods will be invoked by a SyncBackendHost on the same thread
-// used to create that SyncBackendHost.
-class SyncFrontend {
- public:
- typedef sync_api::BaseTransaction BaseTransaction;
- typedef sync_api::SyncManager::ChangeRecord ChangeRecord;
- SyncFrontend() {
- }
-
- // The backend has completed initialization and it is now ready to accept and
- // process changes.
- virtual void OnBackendInitialized() = 0;
-
- // The backend queried the server recently and received some updates.
- virtual void OnSyncCycleCompleted() = 0;
-
- // The backend encountered an authentication problem and requests new
- // credentials to be provided. See SyncBackendHost::Authenticate for details.
- virtual void OnAuthError() = 0;
-
- // Changes have been applied to the backend model and are ready to be
- // applied to the frontend model. See syncapi.h for detailed instructions on
- // how to interpret and process |changes|.
- virtual void ApplyModelChanges(const BaseTransaction* trans,
- const ChangeRecord* changes,
- int change_count) = 0;
- protected:
- // Don't delete through SyncFrontend interface.
- virtual ~SyncFrontend() {
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(SyncFrontend);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/personalization.cc b/chrome/browser/sync/personalization.cc
deleted file mode 100644
index 8f007cf..0000000
--- a/chrome/browser/sync/personalization.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "chrome/browser/sync/personalization.h"
-
-#include "app/resource_bundle.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/string_util.h"
-#include "chrome/app/chrome_dll_resource.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_url_handler.h"
-#include "chrome/browser/command_updater.h"
-#include "chrome/browser/options_window.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/profile_manager.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/jstemplate_builder.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/pref_service.h"
-#include "chrome/browser/dom_ui/new_tab_page_sync_handler.h"
-#include "chrome/browser/sync/personalization_strings.h"
-#include "chrome/browser/sync/auth_error_state.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "googleurl/src/gurl.h"
-#include "grit/app_resources.h"
-#include "grit/browser_resources.h"
-#include "net/url_request/url_request.h"
-
-using sync_api::SyncManager;
-
-// TODO(ncarter): Move these switches into chrome_switches. They are here
-// now because we want to keep them secret during early development.
-namespace switches {
- const wchar_t kSyncServiceURL[] = L"sync-url";
- const wchar_t kSyncServicePort[] = L"sync-port";
- const wchar_t kSyncUserForTest[] = L"sync-user-for-test";
- const wchar_t kSyncPasswordForTest[] = L"sync-password-for-test";
-}
-
-// TODO(munjal): Move these preferences to common/pref_names.h.
-// Names of various preferences.
-namespace prefs {
- const wchar_t kSyncPath[] = L"sync";
- const wchar_t kSyncLastSyncedTime[] = L"sync.last_synced_time";
- const wchar_t kSyncUserName[] = L"sync.username";
- const wchar_t kSyncHasSetupCompleted[] = L"sync.has_setup_completed";
-}
-
-// Top-level path for our network layer DataSource.
-static const char kCloudyResourcesPath[] = "resources";
-// Path for cloudy:stats page.
-static const char kCloudyStatsPath[] = "stats";
-// Path for the gaia sync login dialog.
-static const char kCloudyGaiaLoginPath[] = "gaialogin";
-static const char kCloudyMergeAndSyncPath[] = "mergeandsync";
-static const char kCloudyThrobberPath[] = "throbber.png";
-static const char kCloudySetupFlowPath[] = "setup";
-
-namespace Personalization {
-
-static std::wstring MakeAuthErrorText(AuthErrorState state) {
- switch (state) {
- case AUTH_ERROR_INVALID_GAIA_CREDENTIALS:
- return L"INVALID_GAIA_CREDENTIALS";
- case AUTH_ERROR_USER_NOT_SIGNED_UP:
- return L"USER_NOT_SIGNED_UP";
- case AUTH_ERROR_CONNECTION_FAILED:
- return L"CONNECTION_FAILED";
- default:
- return std::wstring();
- }
-}
-
-bool IsP13NDisabled(Profile* profile) {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kDisableP13n))
- return true;
- return !profile || profile->GetProfilePersonalization() == NULL;
-}
-
-bool NeedsDOMUI(const GURL& url) {
- return url.SchemeIs(kPersonalizationScheme) &&
- (url.path().find(kCloudyGaiaLoginPath) != std::string::npos) ||
- (url.path().find(kCloudySetupFlowPath) != std::string::npos) ||
- (url.path().find(kCloudyMergeAndSyncPath) != std::string::npos);
-}
-
-class CloudyResourceSource : public ChromeURLDataManager::DataSource {
- public:
- CloudyResourceSource()
- : DataSource(kCloudyResourcesPath, MessageLoop::current()) {
- }
- virtual ~CloudyResourceSource() { }
-
- virtual void StartDataRequest(const std::string& path, int request_id);
-
- virtual std::string GetMimeType(const std::string& path) const {
- if (path == kCloudyThrobberPath)
- return "image/png";
- else
- return "text/html";
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(CloudyResourceSource);
-};
-
-class CloudyStatsSource : public ChromeURLDataManager::DataSource {
- public:
- CloudyStatsSource() : DataSource(kCloudyStatsPath, MessageLoop::current()) {
- }
- virtual ~CloudyStatsSource() { }
- virtual void StartDataRequest(const std::string& path, int request_id) {
- std::string response(MakeCloudyStats());
- scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
- html_bytes->data.resize(response.size());
- std::copy(response.begin(), response.end(), html_bytes->data.begin());
- SendResponse(request_id, html_bytes);
- }
- virtual std::string GetMimeType(const std::string& path) const {
- return "text/html";
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(CloudyStatsSource);
-};
-
-DOMMessageHandler* CreateNewTabPageHandler(DOMUI* dom_ui) {
- return (new NewTabPageSyncHandler())->Attach(dom_ui);
-}
-
-std::string GetNewTabSource() {
- static const StringPiece new_tab_html(
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_NEW_TAB_P13N_HTML));
-
- std::string data_uri("data:text/html,");
- data_uri.append(std::string(new_tab_html.data(), new_tab_html.size()));
- return GURL(data_uri).spec();
-}
-
-std::wstring GetMenuItemInfoText(Browser* browser) {
- browser->command_updater()->UpdateCommandEnabled(IDC_P13N_INFO, true);
- return kMenuLabelStartSync;
-}
-
-void HandleMenuItemClick(Profile* p) {
- // The menu item is enabled either when the sync is not enabled by the user
- // or when it's enabled but the user name is empty. In the former case enable
- // sync. In the latter case, show the login dialog.
- ProfileSyncService* service = p->GetProfilePersonalization()->sync_service();
- DCHECK(service);
- if (service->IsSyncEnabledByUser()) {
- ShowOptionsWindow(OPTIONS_PAGE_USER_DATA, OPTIONS_GROUP_NONE, p);
- } else {
- service->EnableForUser();
- }
-}
-
-} // namespace Personalization
-
-class ProfilePersonalizationImpl : public ProfilePersonalization,
- public NotificationObserver {
- public:
- explicit ProfilePersonalizationImpl(Profile *p)
- : profile_(p) {
- // g_browser_process and/or io_thread may not exist during testing.
- if (g_browser_process && g_browser_process->io_thread()) {
- // Add our network layer data source for 'cloudy' URLs.
- // TODO(timsteele): This one belongs in BrowserAboutHandler.
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(&chrome_url_data_manager,
- &ChromeURLDataManager::AddDataSource,
- new Personalization::CloudyStatsSource()));
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(&chrome_url_data_manager,
- &ChromeURLDataManager::AddDataSource,
- new Personalization::CloudyResourceSource()));
- }
-
- registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
- Source<Profile>(profile_));
- }
- virtual ~ProfilePersonalizationImpl() {}
-
- // ProfilePersonalization implementation
- virtual ProfileSyncService* sync_service() {
- if (!sync_service_.get())
- InitSyncService();
- return sync_service_.get();
- }
-
- // NotificationObserver implementation.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK_EQ(type.value, NotificationType::BOOKMARK_MODEL_LOADED);
- if (!sync_service_.get())
- InitSyncService();
- registrar_.RemoveAll();
- }
-
- void InitSyncService() {
- sync_service_.reset(new ProfileSyncService(profile_));
- sync_service_->Initialize();
- }
-
- private:
- Profile* profile_;
- NotificationRegistrar registrar_;
- scoped_ptr<ProfileSyncService> sync_service_;
- DISALLOW_COPY_AND_ASSIGN(ProfilePersonalizationImpl);
-};
-
-namespace Personalization {
-
-void CloudyResourceSource::StartDataRequest(const std::string& path_raw,
- int request_id) {
- scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
- if (path_raw == kCloudyThrobberPath) {
- ResourceBundle::GetSharedInstance().LoadImageResourceBytes(IDR_THROBBER,
- &html_bytes->data);
- SendResponse(request_id, html_bytes);
- return;
- }
-
- std::string response;
- if (path_raw == kCloudyGaiaLoginPath) {
- static const StringPiece html(ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_GAIA_LOGIN_HTML));
- response = html.as_string();
- } else if (path_raw == kCloudyMergeAndSyncPath) {
- static const StringPiece html(ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_MERGE_AND_SYNC_HTML));
- response = html.as_string();
- } else if (path_raw == kCloudySetupFlowPath) {
- static const StringPiece html(ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_SYNC_SETUP_FLOW_HTML));
- response = html.as_string();
- }
- // Send the response.
- html_bytes->data.resize(response.size());
- std::copy(response.begin(), response.end(), html_bytes->data.begin());
- SendResponse(request_id, html_bytes);
-}
-
-ProfilePersonalization* CreateProfilePersonalization(Profile* p) {
- return new ProfilePersonalizationImpl(p);
-}
-
-void CleanupProfilePersonalization(ProfilePersonalization* p) {
- if (p) delete p;
-}
-
-static void AddBoolDetail(ListValue* details, const std::wstring& stat_name,
- bool stat_value) {
- DictionaryValue* val = new DictionaryValue;
- val->SetString(L"stat_name", stat_name);
- val->SetBoolean(L"stat_value", stat_value);
- details->Append(val);
-}
-
-static void AddIntDetail(ListValue* details, const std::wstring& stat_name,
- int64 stat_value) {
- DictionaryValue* val = new DictionaryValue;
- val->SetString(L"stat_name", stat_name);
- val->SetString(L"stat_value", FormatNumber(stat_value));
- details->Append(val);
-}
-
-std::string MakeCloudyStats() {
- FilePath user_data_dir;
- if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
- return std::string();
- ProfileManager* profile_manager = g_browser_process->profile_manager();
- Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
- ProfilePersonalization* p13n_profile = profile->GetProfilePersonalization();
- ProfileSyncService* service = p13n_profile->sync_service();
-
- DictionaryValue strings;
- if (!service->IsSyncEnabledByUser()) {
- strings.SetString(L"summary", L"SYNC DISABLED");
- } else {
- SyncManager::Status full_status(service->QueryDetailedSyncStatus());
-
- strings.SetString(L"summary",
- ProfileSyncService::BuildSyncStatusSummaryText(
- full_status.summary));
-
- strings.Set(L"authenticated",
- new FundamentalValue(full_status.authenticated));
- strings.SetString(L"auth_problem",
- MakeAuthErrorText(service->GetAuthErrorState()));
-
- strings.SetString(L"time_since_sync", service->GetLastSyncedTimeString());
-
- ListValue* details = new ListValue();
- strings.Set(L"details", details);
- AddBoolDetail(details, L"Server Up", full_status.server_up);
- AddBoolDetail(details, L"Server Reachable", full_status.server_reachable);
- AddBoolDetail(details, L"Server Broken", full_status.server_broken);
- AddBoolDetail(details, L"Notifications Enabled",
- full_status.notifications_enabled);
- AddIntDetail(details, L"Notifications Received",
- full_status.notifications_received);
- AddIntDetail(details, L"Notifications Sent",
- full_status.notifications_sent);
- AddIntDetail(details, L"Unsynced Count", full_status.unsynced_count);
- AddIntDetail(details, L"Conflicting Count", full_status.conflicting_count);
- AddBoolDetail(details, L"Syncing", full_status.syncing);
- AddBoolDetail(details, L"Syncer Paused", full_status.syncer_paused);
- AddBoolDetail(details, L"Initial Sync Ended",
- full_status.initial_sync_ended);
- AddBoolDetail(details, L"Syncer Stuck", full_status.syncer_stuck);
- AddIntDetail(details, L"Updates Available", full_status.updates_available);
- AddIntDetail(details, L"Updates Received", full_status.updates_received);
- AddBoolDetail(details, L"Disk Full", full_status.disk_full);
- AddBoolDetail(details, L"Invalid Store", full_status.invalid_store);
- AddIntDetail(details, L"Max Consecutive Errors",
- full_status.max_consecutive_errors);
- }
-
- static const StringPiece sync_html(
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_ABOUT_SYNC_HTML));
-
- return jstemplate_builder::GetTemplateHtml(
- sync_html, &strings , "t" /* template root node id */);
-}
-
-} // namespace Personalization
-
-#endif
diff --git a/chrome/browser/sync/personalization.h b/chrome/browser/sync/personalization.h
deleted file mode 100644
index 2e22e0b..0000000
--- a/chrome/browser/sync/personalization.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-// TODO(timsteele): Remove this file by finding proper homes for everything in
-// trunk.
-#ifndef CHROME_BROWSER_SYNC_PERSONALIZATION_H_
-#define CHROME_BROWSER_SYNC_PERSONALIZATION_H_
-
-#include <string>
-#include "base/basictypes.h"
-#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-
-class Browser;
-class DOMUI;
-class DOMMessageHandler;
-class Profile;
-class RenderView;
-class RenderViewHost;
-class WebFrame;
-class WebView;
-
-class ProfileSyncService;
-class ProfileSyncServiceObserver;
-
-namespace views { class View; }
-
-// TODO(ncarter): Move these switches into chrome_switches. They are here
-// now because we want to keep them secret during early development.
-namespace switches {
-
-extern const wchar_t kSyncServiceURL[];
-extern const wchar_t kSyncServicePort[];
-extern const wchar_t kSyncUserForTest[];
-extern const wchar_t kSyncPasswordForTest[];
-
-}
-
-// Names of various preferences.
-// TODO(munjal): Move these preferences to common/pref_names.h.
-namespace prefs {
-extern const wchar_t kSyncPath[];
-extern const wchar_t kSyncLastSyncedTime[];
-extern const wchar_t kSyncUserName[];
-extern const wchar_t kSyncHasSetupCompleted[];
-}
-
-// Contains a profile sync service, which is initialized at profile creation.
-// A pointer to this class is passed as a handle.
-class ProfilePersonalization {
- public:
- ProfilePersonalization() {}
- virtual ~ProfilePersonalization() {}
-
- virtual ProfileSyncService* sync_service() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProfilePersonalization);
-};
-
-// Contains methods to perform Personalization-related tasks on behalf of the
-// caller.
-namespace Personalization {
-
-// Checks if P13N is globally disabled or not, and that |profile| has a valid
-// ProfilePersonalization member (it can be NULL for TestingProfiles).
-bool IsP13NDisabled(Profile* profile);
-
-// Returns whether |url| should be loaded in a DOMUI.
-bool NeedsDOMUI(const GURL& url);
-
-// Construct a new ProfilePersonalization and return it so the caller can take
-// ownership.
-ProfilePersonalization* CreateProfilePersonalization(Profile* p);
-
-// The caller of Create...() above should call this when the returned
-// ProfilePersonalization object should be deleted.
-void CleanupProfilePersonalization(ProfilePersonalization* p);
-
-// Handler for "cloudy:stats"
-std::string MakeCloudyStats();
-
-// Construct a new DOMMessageHandler for the new tab page |dom_ui|.
-DOMMessageHandler* CreateNewTabPageHandler(DOMUI* dom_ui);
-
-// Get HTML for the Personalization iframe in the New Tab Page.
-std::string GetNewTabSource();
-
-// Returns the text for personalization info menu item and sets its enabled
-// state.
-std::wstring GetMenuItemInfoText(Browser* browser);
-
-// Performs appropriate action when the sync menu item is clicked.
-void HandleMenuItemClick(Profile* p);
-} // namespace Personalization
-
-// The internal scheme used to retrieve HTML resources for personalization
-// related code (e.g cloudy:stats, GAIA login page).
-// We need to ensure the GAIA login HTML is loaded into an HTMLDialogContents.
-// Outside of p13n (for the time being) only "gears://" gives this (see
-// HtmlDialogContents::IsHtmlDialogUrl) for the application shortcut dialog.
-// TODO(timsteele): We should have a robust way to handle this to allow more
-// reuse of our HTML dialog code, perhaps by using a dedicated "dialog-resource"
-// scheme (chrome-resource is coupled to DOM_UI). Figure out if that is the best
-// course of action / pitch this idea to chromium-dev.
-static const char kPersonalizationScheme[] = "cloudy";
-
-#endif // CHROME_BROWSER_SYNC_PERSONALIZATION_H_
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/personalization_strings.h b/chrome/browser/sync/personalization_strings.h
deleted file mode 100644
index ed3036d..0000000
--- a/chrome/browser/sync/personalization_strings.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-// Contains all string resources usec by the personalization module.
-
-// TODO(munjal): This file should go away once the personalization module
-// becomes public. At that point, we have to put all the strings below in the
-// generated resources file.
-
-#ifdef CHROME_PERSONALIZATION
-
-// TODO(timsteele): Rename this file; 'personalization' is deprecated.
-#ifndef CHROME_BROWSER_SYNC_PERSONALIZATION_STRINGS_H_
-#define CHROME_BROWSER_SYNC_PERSONALIZATION_STRINGS_H_
-
-// User Data tab in the Options menu.
-static const wchar_t kSyncGroupName[] = L"Bookmark Sync:";
-static const wchar_t kSyncNotSetupInfo[] =
- L"You are not set up to sync your bookmarks with your other computers.";
-static const wchar_t kStartSyncButtonLabel[] = L"Synchronize my bookmarks...";
-static const wchar_t kSyncAccountLabel[] = L"Synced to ";
-static const wchar_t kLastSyncedLabel[] = L"Last synced: ";
-static const wchar_t kSyncCredentialsNeededLabel[] =
- L"Account login details are not yet entered.";
-static const wchar_t kSyncAuthenticatingLabel[] = L"Authenticating...";
-static const wchar_t kSyncInvalidCredentialsError[] =
- L"Invalid user name or password.";
-static const wchar_t kSyncOtherLoginErrorLabel[] =
- L"Error signing in.";
-static const wchar_t kSyncExpiredCredentialsError[] =
- L"Login details are out of date.";
-static const wchar_t kSyncServerNotReachableError[] =
- L"Sync server is not reachable. Retrying...";
-static const wchar_t kSyncReLoginLinkLabel[] = L"Login again";
-static const wchar_t kStopSyncButtonLabel[] = L"Stop syncing this account";
-
-// Sync status messages.
-static const wchar_t kLastSyncedTimeNever[] = L"Never.";
-static const wchar_t kLastSyncedTimeWithinLastMinute[] = L"Just now.";
-
-// Sync merge warning dialog strings.
-static const wchar_t kMergeWarningMessageText[] =
- L"WARNING: Your existing online bookmarks will be merged with the "
- L"bookmarks on this machine. You can use the Bookmark Manager to organize "
- L"your bookmarks after the merge.";
-static const wchar_t kCancelSyncButtonLabel[] = L"Cancel";
-static const wchar_t kMergeAndSyncButtonLabel[] = L"Merge and Sync";
-
-// Various strings for the new tab page personalization.
-static const char kSyncSectionTitle[] = "Bookmark Sync";
-static const char kSyncErrorSectionTitle[] = "Bookmark Sync Error!";
-static const char kSyncPromotionMsg[] =
- "You can sync your bookmarks across computers using your Google account.";
-static const wchar_t kSyncServerUnavailableMsg[] =
- L"Google Chrome could not sync your bookmarks because it could not connect "
- L"to the sync server. Retrying...";
-static const char kStartNowLinkText[] = "Start now.";
-static const char kSettingUpText[] = "Setup in progress...";
-
-// Sync menu item strings.
-static const wchar_t kMenuLabelStartSync[] = L"Sync my bookmarks...";
-
-// Login dialog strings.
-static const wchar_t kLoginDialogTitle[] = L"Sync my bookmarks";
-
-#endif // CHROME_BROWSER_SYNC_PERSONALIZATION_STRINGS_H_
-
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
deleted file mode 100644
index e596e28..0000000
--- a/chrome/browser/sync/profile_sync_service.cc
+++ /dev/null
@@ -1,886 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-#include "chrome/browser/sync/profile_sync_service.h"
-
-#include <stack>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/gfx/png_encoder.h"
-#include "base/stl_util-inl.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "chrome/browser/bookmarks/bookmark_utils.h"
-#include "chrome/browser/history/history_notifications.h"
-#include "chrome/browser/history/history_types.h"
-#include "chrome/browser/profile.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_service.h"
-#include "chrome/common/time_format.h"
-#include "chrome/browser/sync/personalization.h"
-#include "chrome/browser/sync/personalization_strings.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "views/window/window.h"
-
-using browser_sync::ModelAssociator;
-using browser_sync::SyncBackendHost;
-
-ProfileSyncService::ProfileSyncService(Profile* profile)
- : last_auth_error_(AUTH_ERROR_NONE),
- profile_(profile),
- backend_initialized_(false),
- expecting_first_run_auth_needed_event_(false),
- is_auth_in_progress_(false),
- ready_to_process_changes_(false),
- unrecoverable_error_detected_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)) {
-}
-
-ProfileSyncService::~ProfileSyncService() {
- Shutdown(false);
-}
-
-void ProfileSyncService::Initialize() {
- InitSettings();
- RegisterPreferences();
- if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted))
- DisableForUser(); // Clean up in case of previous crash / setup abort.
- else
- StartUp();
-}
-
-void ProfileSyncService::InitSettings() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- // Override the sync server URL from the command-line, if sync server and sync
- // port command-line arguments exist.
- if (command_line.HasSwitch(switches::kSyncServiceURL)) {
- std::wstring value(command_line.GetSwitchValue(switches::kSyncServiceURL));
- if (!value.empty()) {
- GURL custom_sync_url(WideToUTF8(value));
- if (custom_sync_url.is_valid()) {
- sync_service_url_ = custom_sync_url;
- } else {
- LOG(WARNING) << "The following sync URL specified at the command-line "
- << "is invalid: " << value;
- }
- }
- } else {
- NOTREACHED() << "--sync-url is required when sync is enabled.";
- }
-
- if (command_line.HasSwitch(switches::kSyncServicePort)) {
- std::string port_str = WideToUTF8(command_line.GetSwitchValue(
- switches::kSyncServicePort));
- if (!port_str.empty()) {
- GURL::Replacements replacements;
- replacements.SetPortStr(port_str);
- sync_service_url_ = sync_service_url_.ReplaceComponents(replacements);
- }
- }
-}
-
-void ProfileSyncService::RegisterPreferences() {
- PrefService* pref_service = profile_->GetPrefs();
- if (pref_service->IsPrefRegistered(prefs::kSyncUserName))
- return;
- pref_service->RegisterStringPref(prefs::kSyncUserName, std::wstring());
- pref_service->RegisterStringPref(prefs::kSyncLastSyncedTime, std::wstring());
- pref_service->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, false);
-}
-
-void ProfileSyncService::LoadPreferences() {
- PrefService* pref_service = profile_->GetPrefs();
- std::wstring last_synced_time_string =
- pref_service->GetString(prefs::kSyncLastSyncedTime);
- if (!last_synced_time_string.empty()) {
- int64 last_synced_time;
- bool success = StringToInt64(WideToUTF16(last_synced_time_string),
- &last_synced_time);
- if (success) {
- last_synced_time_ = base::Time::FromInternalValue(last_synced_time);
- } else {
- NOTREACHED();
- }
- }
-}
-
-void ProfileSyncService::ClearPreferences() {
- PrefService* pref_service = profile_->GetPrefs();
- pref_service->ClearPref(prefs::kSyncUserName);
- pref_service->ClearPref(prefs::kSyncLastSyncedTime);
- pref_service->ClearPref(prefs::kSyncHasSetupCompleted);
-
- pref_service->ScheduleSavePersistentPrefs();
-}
-
-void ProfileSyncService::InitializeBackend() {
- backend_->Initialize(sync_service_url_);
-}
-
-void ProfileSyncService::StartUp() {
- // Don't start up multiple times.
- if (backend_.get())
- return;
-
- LoadPreferences();
-
- backend_.reset(new SyncBackendHost(this, profile_->GetPath()));
-
- // We add ourselves as an observer, and we remain one forever. Note we don't
- // keep any pointer to the model, we just receive notifications from it.
- BookmarkModel* model = profile_->GetBookmarkModel();
- model->AddObserver(this);
-
- // Create new model assocation manager.
- model_associator_ = new ModelAssociator(this);
-
- // TODO(timsteele): HttpBridgeFactory should take a const* to the profile's
- // URLRequestContext, because it needs it to create HttpBridge objects, and
- // it may need to do that before the default request context has been set
- // up. For now, call GetRequestContext lazy-init to force creation.
- profile_->GetRequestContext();
- InitializeBackend();
-}
-
-void ProfileSyncService::Shutdown(bool sync_disabled) {
- if (backend_.get()) {
- backend_->Shutdown(sync_disabled);
- backend_.reset();
- }
-
- BookmarkModel* model = profile_->GetBookmarkModel();
- if (model)
- model->RemoveObserver(this);
-
- // Clear all assocations and throw away the assocation manager instance.
- if (model_associator_.get()) {
- model_associator_->ClearAll();
- model_associator_ = NULL;
- }
-
- // Clear various flags.
- is_auth_in_progress_ = false;
- backend_initialized_ = false;
- expecting_first_run_auth_needed_event_ = false;
- ready_to_process_changes_ = false;
- last_attempted_user_email_.clear();
-}
-
-void ProfileSyncService::EnableForUser() {
- if (wizard_.IsVisible()) {
- // TODO(timsteele): Focus wizard.
- return;
- }
- expecting_first_run_auth_needed_event_ = true;
-
- StartUp();
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::DisableForUser() {
- if (wizard_.IsVisible()) {
- // TODO(timsteele): Focus wizard.
- return;
- }
- Shutdown(true);
- ClearPreferences();
-
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::Loaded(BookmarkModel* model) {
- StartProcessingChangesIfReady();
-}
-
-void ProfileSyncService::UpdateSyncNodeProperties(const BookmarkNode* src,
- sync_api::WriteNode* dst) {
- // Set the properties of the item.
- dst->SetIsFolder(src->is_folder());
- dst->SetTitle(WideToUTF16(src->GetTitle()).c_str());
- // URL is passed as a C string here because this interface avoids
- // string16. SetURL copies the data into its own memory.
- string16 url = UTF8ToUTF16(src->GetURL().spec());
- dst->SetURL(url.c_str());
- SetSyncNodeFavicon(src, dst);
-}
-
-void ProfileSyncService::EncodeFavicon(const BookmarkNode* src,
- std::vector<unsigned char>* dst) const {
- const SkBitmap& favicon = profile_->GetBookmarkModel()->GetFavIcon(src);
-
- dst->clear();
-
- // Check for zero-dimension images. This can happen if the favicon is
- // still being loaded.
- if (favicon.empty())
- return;
-
- // Re-encode the BookmarkNode's favicon as a PNG, and pass the data to the
- // sync subsystem.
- if (!PNGEncoder::EncodeBGRASkBitmap(favicon, false, dst))
- return;
-}
-
-void ProfileSyncService::RemoveOneSyncNode(sync_api::WriteTransaction* trans,
- const BookmarkNode* node) {
- sync_api::WriteNode sync_node(trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->id(), &sync_node)) {
- SetUnrecoverableError();
- return;
- }
- // This node should have no children.
- DCHECK(sync_node.GetFirstChildId() == sync_api::kInvalidId);
- // Remove association and delete the sync node.
- model_associator_->DisassociateIds(sync_node.GetId());
- sync_node.Remove();
-}
-
-void ProfileSyncService::RemoveSyncNodeHierarchy(const BookmarkNode* topmost) {
- sync_api::WriteTransaction trans(backend_->GetUserShareHandle());
-
- // Later logic assumes that |topmost| has been unlinked.
- DCHECK(!topmost->GetParent());
-
- // A BookmarkModel deletion event means that |node| and all its children were
- // deleted. Sync backend expects children to be deleted individually, so we do
- // a depth-first-search here. At each step, we consider the |index|-th child
- // of |node|. |index_stack| stores index values for the parent levels.
- std::stack<int> index_stack;
- index_stack.push(0); // For the final pop. It's never used.
- const BookmarkNode* node = topmost;
- int index = 0;
- while (node) {
- // The top of |index_stack| should always be |node|'s index.
- DCHECK(!node->GetParent() || (node->GetParent()->IndexOfChild(node) ==
- index_stack.top()));
- if (index == node->GetChildCount()) {
- // If we've processed all of |node|'s children, delete |node| and move
- // on to its successor.
- RemoveOneSyncNode(&trans, node);
- node = node->GetParent();
- index = index_stack.top() + 1; // (top() + 0) was what we removed.
- index_stack.pop();
- } else {
- // If |node| has an unprocessed child, process it next after pushing the
- // current state onto the stack.
- DCHECK_LT(index, node->GetChildCount());
- index_stack.push(index);
- node = node->GetChild(index);
- index = 0;
- }
- }
- DCHECK(index_stack.empty()); // Nothing should be left on the stack.
-}
-
-bool ProfileSyncService::MergeAndSyncAcceptanceNeeded() const {
- // If we've shown the dialog before, don't show it again.
- if (profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted))
- return false;
-
- return model_associator_->BookmarkModelHasUserCreatedNodes() &&
- model_associator_->SyncModelHasUserCreatedNodes();
-}
-
-bool ProfileSyncService::IsSyncEnabledByUser() const {
- return profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted);
-}
-
-void ProfileSyncService::UpdateLastSyncedTime() {
- last_synced_time_ = base::Time::Now();
- profile_->GetPrefs()->SetString(prefs::kSyncLastSyncedTime,
- Int64ToWString(last_synced_time_.ToInternalValue()));
-}
-
-void ProfileSyncService::BookmarkNodeAdded(BookmarkModel* model,
- const BookmarkNode* parent,
- int index) {
- if (!ShouldPushChanges())
- return;
-
- DCHECK(backend_->GetUserShareHandle());
-
- // Acquire a scoped write lock via a transaction.
- sync_api::WriteTransaction trans(backend_->GetUserShareHandle());
-
- CreateSyncNode(parent, index, &trans);
-}
-
-int64 ProfileSyncService::CreateSyncNode(const BookmarkNode* parent,
- int index,
- sync_api::WriteTransaction* trans) {
- const BookmarkNode* child = parent->GetChild(index);
- DCHECK(child);
-
- // Create a WriteNode container to hold the new node.
- sync_api::WriteNode sync_child(trans);
-
- // Actually create the node with the appropriate initial position.
- if (!PlaceSyncNode(CREATE, parent, index, trans, &sync_child)) {
- LOG(WARNING) << "Sync node creation failed; recovery unlikely";
- SetUnrecoverableError();
- return sync_api::kInvalidId;
- }
-
- UpdateSyncNodeProperties(child, &sync_child);
-
- // Associate the ID from the sync domain with the bookmark node, so that we
- // can refer back to this item later.
- model_associator_->AssociateIds(child->id(), sync_child.GetId());
-
- return sync_child.GetId();
-}
-
-void ProfileSyncService::BookmarkNodeRemoved(BookmarkModel* model,
- const BookmarkNode* parent,
- int index,
- const BookmarkNode* node) {
- if (!ShouldPushChanges())
- return;
-
- RemoveSyncNodeHierarchy(node);
-}
-
-void ProfileSyncService::BookmarkNodeChanged(BookmarkModel* model,
- const BookmarkNode* node) {
- if (!ShouldPushChanges())
- return;
-
- // We shouldn't see changes to the top-level nodes.
- DCHECK_NE(node, model->GetBookmarkBarNode());
- DCHECK_NE(node, model->other_node());
-
- // Acquire a scoped write lock via a transaction.
- sync_api::WriteTransaction trans(backend_->GetUserShareHandle());
-
- // Lookup the sync node that's associated with |node|.
- sync_api::WriteNode sync_node(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->id(), &sync_node)) {
- SetUnrecoverableError();
- return;
- }
-
- UpdateSyncNodeProperties(node, &sync_node);
-
- DCHECK_EQ(sync_node.GetIsFolder(), node->is_folder());
- DCHECK_EQ(model_associator_->GetBookmarkNodeFromSyncId(
- sync_node.GetParentId()),
- node->GetParent());
- // This node's index should be one more than the predecessor's index.
- DCHECK_EQ(node->GetParent()->IndexOfChild(node),
- CalculateBookmarkModelInsertionIndex(node->GetParent(),
- &sync_node));
-}
-
-void ProfileSyncService::BookmarkNodeMoved(BookmarkModel* model,
- const BookmarkNode* old_parent,
- int old_index,
- const BookmarkNode* new_parent,
- int new_index) {
- if (!ShouldPushChanges())
- return;
-
- const BookmarkNode* child = new_parent->GetChild(new_index);
- // We shouldn't see changes to the top-level nodes.
- DCHECK_NE(child, model->GetBookmarkBarNode());
- DCHECK_NE(child, model->other_node());
-
- // Acquire a scoped write lock via a transaction.
- sync_api::WriteTransaction trans(backend_->GetUserShareHandle());
-
- // Lookup the sync node that's associated with |child|.
- sync_api::WriteNode sync_node(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(child->id(),
- &sync_node)) {
- SetUnrecoverableError();
- return;
- }
-
- if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node)) {
- SetUnrecoverableError();
- return;
- }
-}
-
-void ProfileSyncService::BookmarkNodeFavIconLoaded(BookmarkModel* model,
- const BookmarkNode* node) {
- BookmarkNodeChanged(model, node);
-}
-
-void ProfileSyncService::BookmarkNodeChildrenReordered(
- BookmarkModel* model, const BookmarkNode* node) {
- if (!ShouldPushChanges())
- return;
-
- // Acquire a scoped write lock via a transaction.
- sync_api::WriteTransaction trans(backend_->GetUserShareHandle());
-
- // The given node's children got reordered. We need to reorder all the
- // children of the corresponding sync node.
- for (int i = 0; i < node->GetChildCount(); ++i) {
- sync_api::WriteNode sync_child(&trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(node->GetChild(i)->id(),
- &sync_child)) {
- SetUnrecoverableError();
- return;
- }
- DCHECK_EQ(sync_child.GetParentId(),
- model_associator_->GetSyncIdFromBookmarkId(node->id()));
-
- if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child)) {
- SetUnrecoverableError();
- return;
- }
- }
-}
-
-bool ProfileSyncService::PlaceSyncNode(MoveOrCreate operation,
- const BookmarkNode* parent,
- int index,
- sync_api::WriteTransaction* trans,
- sync_api::WriteNode* dst) {
- sync_api::ReadNode sync_parent(trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(parent->id(),
- &sync_parent)) {
- LOG(WARNING) << "Parent lookup failed";
- SetUnrecoverableError();
- return false;
- }
-
- bool success = false;
- if (index == 0) {
- // Insert into first position.
- success = (operation == CREATE) ? dst->InitByCreation(sync_parent, NULL) :
- dst->SetPosition(sync_parent, NULL);
- if (success) {
- DCHECK_EQ(dst->GetParentId(), sync_parent.GetId());
- DCHECK_EQ(dst->GetId(), sync_parent.GetFirstChildId());
- DCHECK_EQ(dst->GetPredecessorId(), sync_api::kInvalidId);
- }
- } else {
- // Find the bookmark model predecessor, and insert after it.
- const BookmarkNode* prev = parent->GetChild(index - 1);
- sync_api::ReadNode sync_prev(trans);
- if (!model_associator_->InitSyncNodeFromBookmarkId(prev->id(),
- &sync_prev)) {
- LOG(WARNING) << "Predecessor lookup failed";
- return false;
- }
- success = (operation == CREATE) ?
- dst->InitByCreation(sync_parent, &sync_prev) :
- dst->SetPosition(sync_parent, &sync_prev);
- if (success) {
- DCHECK_EQ(dst->GetParentId(), sync_parent.GetId());
- DCHECK_EQ(dst->GetPredecessorId(), sync_prev.GetId());
- DCHECK_EQ(dst->GetId(), sync_prev.GetSuccessorId());
- }
- }
- return success;
-}
-
-// An invariant has been violated. Transition to an error state where we try
-// to do as little work as possible, to avoid further corruption or crashes.
-void ProfileSyncService::SetUnrecoverableError() {
- unrecoverable_error_detected_ = true;
- LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable.";
-}
-
-// Determine the bookmark model index to which a node must be moved so that
-// predecessor of the node (in the bookmark model) matches the predecessor of
-// |source| (in the sync model).
-// As a precondition, this assumes that the predecessor of |source| has been
-// updated and is already in the correct position in the bookmark model.
-int ProfileSyncService::CalculateBookmarkModelInsertionIndex(
- const BookmarkNode* parent,
- const sync_api::BaseNode* child_info) const {
- DCHECK(parent);
- DCHECK(child_info);
- int64 predecessor_id = child_info->GetPredecessorId();
- // A return ID of kInvalidId indicates no predecessor.
- if (predecessor_id == sync_api::kInvalidId)
- return 0;
-
- // Otherwise, insert after the predecessor bookmark node.
- const BookmarkNode* predecessor =
- model_associator_->GetBookmarkNodeFromSyncId(predecessor_id);
- DCHECK(predecessor);
- DCHECK_EQ(predecessor->GetParent(), parent);
- return parent->IndexOfChild(predecessor) + 1;
-}
-
-void ProfileSyncService::OnBackendInitialized() {
- backend_initialized_ = true;
-
- PrefService* pref_service = profile_->GetPrefs();
- DCHECK(pref_service->IsPrefRegistered(prefs::kSyncUserName));
- pref_service->SetString(prefs::kSyncUserName,
- UTF16ToWide(backend_->GetAuthenticatedUsername()));
- StartProcessingChangesIfReady();
-
- // The very first time the backend initializes is effectively the first time
- // we can say we successfully "synced". last_synced_time_ will only be null
- // in this case, because the pref wasn't restored on StartUp.
- if (last_synced_time_.is_null())
- UpdateLastSyncedTime();
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::OnSyncCycleCompleted() {
- UpdateLastSyncedTime();
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::OnAuthError() {
- last_auth_error_ = backend_->GetAuthErrorState();
- // Protect against the in-your-face dialogs that pop out of nowhere.
- // Require the user to click somewhere to run the setup wizard in the case
- // of a steady-state auth failure.
- if (wizard_.IsVisible() || expecting_first_run_auth_needed_event_) {
- wizard_.Step(AUTH_ERROR_NONE == backend_->GetAuthErrorState() ?
- SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GAIA_LOGIN);
- }
-
- if (expecting_first_run_auth_needed_event_) {
- last_auth_error_ = AUTH_ERROR_NONE;
- expecting_first_run_auth_needed_event_ = false;
- }
-
- is_auth_in_progress_ = false;
- // Fan the notification out to interested UI-thread components.
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::ShowLoginDialog() {
- if (wizard_.IsVisible())
- return;
- if (last_auth_error_ != AUTH_ERROR_NONE)
- wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
-}
-
-// ApplyModelChanges is called by the sync backend after changes have been made
-// to the sync engine's model. Apply these changes to the browser bookmark
-// model.
-void ProfileSyncService::ApplyModelChanges(
- const sync_api::BaseTransaction* trans,
- const sync_api::SyncManager::ChangeRecord* changes,
- int change_count) {
- if (!ShouldPushChanges())
- return;
-
- // A note about ordering. Sync backend is responsible for ordering the change
- // records in the following order:
- //
- // 1. Deletions, from leaves up to parents.
- // 2. Existing items with synced parents & predecessors.
- // 3. New items with synced parents & predecessors.
- // 4. Items with parents & predecessors in the list.
- // 5. Repeat #4 until all items are in the list.
- //
- // "Predecessor" here means the previous item within a given folder; an item
- // in the first position is always said to have a synced predecessor.
- // For the most part, applying these changes in the order given will yield
- // the correct result. There is one exception, however: for items that are
- // moved away from a folder that is being deleted, we will process the delete
- // before the move. Since deletions in the bookmark model propagate from
- // parent to child, we must move them to a temporary location.
- BookmarkModel* model = profile_->GetBookmarkModel();
-
- // We are going to make changes to the bookmarks model, but don't want to end
- // up in a feedback loop, so remove ourselves as an observer while applying
- // changes.
- model->RemoveObserver(this);
-
- // A parent to hold nodes temporarily orphaned by parent deletion. It is
- // lazily created inside the loop.
- const BookmarkNode* foster_parent = NULL;
- for (int i = 0; i < change_count; ++i) {
- const BookmarkNode* dst =
- model_associator_->GetBookmarkNodeFromSyncId(changes[i].id);
- // Ignore changes to the permanent top-level nodes. We only care about
- // their children.
- if ((dst == model->GetBookmarkBarNode()) || (dst == model->other_node()))
- continue;
- if (changes[i].action ==
- sync_api::SyncManager::ChangeRecord::ACTION_DELETE) {
- // Deletions should always be at the front of the list.
- DCHECK(i == 0 || changes[i-1].action == changes[i].action);
- // Children of a deleted node should not be deleted; they may be
- // reparented by a later change record. Move them to a temporary place.
- DCHECK(dst) << "Could not find node to be deleted";
- const BookmarkNode* parent = dst->GetParent();
- if (dst->GetChildCount()) {
- if (!foster_parent) {
- foster_parent = model->AddGroup(model->other_node(),
- model->other_node()->GetChildCount(),
- std::wstring());
- }
- for (int i = dst->GetChildCount() - 1; i >= 0; --i) {
- model->Move(dst->GetChild(i), foster_parent,
- foster_parent->GetChildCount());
- }
- }
- DCHECK_EQ(dst->GetChildCount(), 0) << "Node being deleted has children";
- model->Remove(parent, parent->IndexOfChild(dst));
- dst = NULL;
- model_associator_->DisassociateIds(changes[i].id);
- } else {
- DCHECK_EQ((changes[i].action ==
- sync_api::SyncManager::ChangeRecord::ACTION_ADD), (dst == NULL))
- << "ACTION_ADD should be seen if and only if the node is unknown.";
-
- sync_api::ReadNode src(trans);
- if (!src.InitByIdLookup(changes[i].id)) {
- LOG(ERROR) << "ApplyModelChanges was passed a bad ID";
- SetUnrecoverableError();
- return;
- }
-
- CreateOrUpdateBookmarkNode(&src, model);
- }
- }
- // Clean up the temporary node.
- if (foster_parent) {
- // There should be no nodes left under the foster parent.
- DCHECK_EQ(foster_parent->GetChildCount(), 0);
- model->Remove(foster_parent->GetParent(),
- foster_parent->GetParent()->IndexOfChild(foster_parent));
- foster_parent = NULL;
- }
-
- // We are now ready to hear about bookmarks changes again.
- model->AddObserver(this);
-}
-
-// Create a bookmark node corresponding to |src| if one is not already
-// associated with |src|.
-const BookmarkNode* ProfileSyncService::CreateOrUpdateBookmarkNode(
- sync_api::BaseNode* src,
- BookmarkModel* model) {
- const BookmarkNode* parent =
- model_associator_->GetBookmarkNodeFromSyncId(src->GetParentId());
- if (!parent) {
- DLOG(WARNING) << "Could not find parent of node being added/updated."
- << " Node title: " << src->GetTitle()
- << ", parent id = " << src->GetParentId();
- return NULL;
- }
- int index = CalculateBookmarkModelInsertionIndex(parent, src);
- const BookmarkNode* dst = model_associator_->GetBookmarkNodeFromSyncId(
- src->GetId());
- if (!dst) {
- dst = CreateBookmarkNode(src, parent, index);
- model_associator_->AssociateIds(dst->id(), src->GetId());
- } else {
- // URL and is_folder are not expected to change.
- // TODO(ncarter): Determine if such changes should be legal or not.
- DCHECK_EQ(src->GetIsFolder(), dst->is_folder());
-
- // Handle reparenting and/or repositioning.
- model->Move(dst, parent, index);
-
- // Handle title update and URL changes due to possible conflict resolution
- // that can happen if both a local user change and server change occur
- // within a sufficiently small time interval.
- const BookmarkNode* old_dst = dst;
- dst = bookmark_utils::ApplyEditsWithNoGroupChange(model, parent, dst,
- UTF16ToWide(src->GetTitle()),
- src->GetIsFolder() ? GURL() : GURL(src->GetURL()),
- NULL); // NULL because we don't need a BookmarkEditor::Handler.
- if (dst != old_dst) { // dst was replaced with a new node with new URL.
- model_associator_->DisassociateIds(src->GetId());
- model_associator_->AssociateIds(dst->id(), src->GetId());
- }
- SetBookmarkFavicon(src, dst);
- }
-
- return dst;
-}
-
-// Creates a bookmark node under the given parent node from the given sync
-// node. Returns the newly created node.
-const BookmarkNode* ProfileSyncService::CreateBookmarkNode(
- sync_api::BaseNode* sync_node,
- const BookmarkNode* parent,
- int index) const {
- DCHECK(parent);
- DCHECK(index >= 0 && index <= parent->GetChildCount());
- BookmarkModel* model = profile_->GetBookmarkModel();
-
- const BookmarkNode* node;
- if (sync_node->GetIsFolder()) {
- node = model->AddGroup(parent, index, UTF16ToWide(sync_node->GetTitle()));
- } else {
- GURL url(sync_node->GetURL());
- node = model->AddURL(parent, index, UTF16ToWide(sync_node->GetTitle()), url);
- SetBookmarkFavicon(sync_node, node);
- }
- return node;
-}
-
-// Sets the favicon of the given bookmark node from the given sync node.
-bool ProfileSyncService::SetBookmarkFavicon(
- sync_api::BaseNode* sync_node,
- const BookmarkNode* bookmark_node) const {
- size_t icon_size = 0;
- const unsigned char* icon_bytes = sync_node->GetFaviconBytes(&icon_size);
- if (!icon_size || !icon_bytes)
- return false;
-
- // Registering a favicon requires that we provide a source URL, but we
- // don't know where these came from. Currently we just use the
- // destination URL, which is not correct, but since the favicon URL
- // is used as a key in the history's thumbnail DB, this gives us a value
- // which does not collide with others.
- GURL fake_icon_url = bookmark_node->GetURL();
-
- std::vector<unsigned char> icon_bytes_vector(icon_bytes,
- icon_bytes + icon_size);
-
- HistoryService* history =
- profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
-
- history->AddPage(bookmark_node->GetURL());
- history->SetFavIcon(bookmark_node->GetURL(),
- fake_icon_url,
- icon_bytes_vector);
-
- return true;
-}
-
-void ProfileSyncService::SetSyncNodeFavicon(
- const BookmarkNode* bookmark_node,
- sync_api::WriteNode* sync_node) const {
- std::vector<unsigned char> favicon_bytes;
- EncodeFavicon(bookmark_node, &favicon_bytes);
- if (!favicon_bytes.empty())
- sync_node->SetFaviconBytes(&favicon_bytes[0], favicon_bytes.size());
-}
-
-SyncBackendHost::StatusSummary ProfileSyncService::QuerySyncStatusSummary() {
- return backend_->GetStatusSummary();
-}
-
-SyncBackendHost::Status ProfileSyncService::QueryDetailedSyncStatus() {
- return backend_->GetDetailedStatus();
-}
-
-std::wstring ProfileSyncService::BuildSyncStatusSummaryText(
- const sync_api::SyncManager::Status::Summary& summary) {
- switch (summary) {
- case sync_api::SyncManager::Status::OFFLINE:
- return L"OFFLINE";
- case sync_api::SyncManager::Status::OFFLINE_UNSYNCED:
- return L"OFFLINE_UNSYNCED";
- case sync_api::SyncManager::Status::SYNCING:
- return L"SYNCING";
- case sync_api::SyncManager::Status::READY:
- return L"READY";
- case sync_api::SyncManager::Status::PAUSED:
- return L"PAUSED";
- case sync_api::SyncManager::Status::CONFLICT:
- return L"CONFLICT";
- case sync_api::SyncManager::Status::OFFLINE_UNUSABLE:
- return L"OFFLINE_UNUSABLE";
- case sync_api::SyncManager::Status::INVALID: // fall through
- default:
- return L"UNKNOWN";
- }
-}
-
-std::wstring ProfileSyncService::GetLastSyncedTimeString() const {
- if (last_synced_time_.is_null())
- return kLastSyncedTimeNever;
-
- base::TimeDelta last_synced = base::Time::Now() - last_synced_time_;
-
- if (last_synced < base::TimeDelta::FromMinutes(1))
- return kLastSyncedTimeWithinLastMinute;
-
- return TimeFormat::TimeElapsed(last_synced);
-}
-
-string16 ProfileSyncService::GetAuthenticatedUsername() const {
- return backend_->GetAuthenticatedUsername();
-}
-
-void ProfileSyncService::OnUserSubmittedAuth(
- const std::string& username, const std::string& password) {
- last_attempted_user_email_ = username;
- is_auth_in_progress_ = true;
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
- backend_->Authenticate(username, password);
-}
-
-void ProfileSyncService::OnUserAcceptedMergeAndSync() {
- bool merge_success = model_associator_->AssociateModels();
- wizard_.Step(SyncSetupWizard::DONE); // TODO(timsteele): error state?
- if (!merge_success) {
- LOG(ERROR) << "Model assocation failed.";
- SetUnrecoverableError();
- return;
- }
-
- ready_to_process_changes_ = true;
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::OnUserCancelledDialog() {
- if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
- // A sync dialog was aborted before authentication or merge acceptance.
- // Rollback.
- DisableForUser();
- }
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::StartProcessingChangesIfReady() {
- BookmarkModel* model = profile_->GetBookmarkModel();
-
- DCHECK(!ready_to_process_changes_);
-
- // First check if the subsystems are ready. We can't proceed until they
- // both have finished loading.
- if (!model->IsLoaded())
- return;
- if (!backend_initialized_)
- return;
-
- // Show the sync merge warning dialog if needed.
- if (MergeAndSyncAcceptanceNeeded()) {
- wizard_.Step(SyncSetupWizard::MERGE_AND_SYNC);
- return;
- }
-
- // We're ready to merge the models.
- bool merge_success = model_associator_->AssociateModels();
- wizard_.Step(SyncSetupWizard::DONE); // TODO(timsteele): error state?
- if (!merge_success) {
- LOG(ERROR) << "Model assocation failed.";
- SetUnrecoverableError();
- return;
- }
-
- ready_to_process_changes_ = true;
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
-void ProfileSyncService::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void ProfileSyncService::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-bool ProfileSyncService::ShouldPushChanges() {
- return ready_to_process_changes_ && // Wait for model load and merge.
- !unrecoverable_error_detected_; // Halt after any terrible events.
-}
-
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
deleted file mode 100644
index 288752f..0000000
--- a/chrome/browser/sync/profile_sync_service.h
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_
-#define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_
-
-#include <string>
-#include <map>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/file_path.h"
-#include "base/observer_list.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/sync/glue/model_associator.h"
-#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/views/sync/sync_setup_wizard.h"
-#include "googleurl/src/gurl.h"
-
-class CommandLine;
-class MessageLoop;
-class Profile;
-
-namespace browser_sync {
-class ModelAssociator;
-}
-
-// Various UI components such as the New Tab page can be driven by observing
-// the ProfileSyncService through this interface.
-class ProfileSyncServiceObserver {
- public:
- // When one of the following events occurs, OnStateChanged() is called.
- // Observers should query the service to determine what happened.
- // - We initialized successfully.
- // - There was an authentication error and the user needs to reauthenticate.
- // - The sync servers are unavailable at this time.
- // - Credentials are now in flight for authentication.
- virtual void OnStateChanged() = 0;
- protected:
- virtual ~ProfileSyncServiceObserver() { }
-};
-
-// ProfileSyncService is the layer between browser subsystems like bookmarks,
-// and the sync backend.
-class ProfileSyncService : public BookmarkModelObserver,
- public browser_sync::SyncFrontend {
- public:
- typedef ProfileSyncServiceObserver Observer;
- typedef browser_sync::SyncBackendHost::Status Status;
-
- ProfileSyncService(Profile* profile);
- virtual ~ProfileSyncService();
-
- // Initializes the object. This should be called every time an object of this
- // class is constructed.
- void Initialize();
-
- // Enables/disables sync for user.
- virtual void EnableForUser();
- virtual void DisableForUser();
-
- // Whether sync is enabled by user or not.
- bool IsSyncEnabledByUser() const;
-
- // BookmarkModelObserver implementation.
- virtual void Loaded(BookmarkModel* model);
- virtual void BookmarkModelBeingDeleted(BookmarkModel* model) {}
- virtual void BookmarkNodeMoved(BookmarkModel* model,
- const BookmarkNode* old_parent,
- int old_index,
- const BookmarkNode* new_parent,
- int new_index);
- virtual void BookmarkNodeAdded(BookmarkModel* model,
- const BookmarkNode* parent,
- int index);
- virtual void BookmarkNodeRemoved(BookmarkModel* model,
- const BookmarkNode* parent,
- int index,
- const BookmarkNode* node);
- virtual void BookmarkNodeChanged(BookmarkModel* model,
- const BookmarkNode* node);
- virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
- const BookmarkNode* node);
- virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
- const BookmarkNode* node);
-
- // SyncFrontend implementation.
- virtual void OnBackendInitialized();
- virtual void OnSyncCycleCompleted();
- virtual void OnAuthError();
- virtual void ApplyModelChanges(
- const sync_api::BaseTransaction* trans,
- const sync_api::SyncManager::ChangeRecord* changes,
- int change_count);
-
- // Called when a user enters credentials through UI.
- virtual void OnUserSubmittedAuth(const std::string& username,
- const std::string& password);
-
- // Called when a user decides whether to merge and sync or abort.
- virtual void OnUserAcceptedMergeAndSync();
-
- // Called when a user cancels any setup dialog (login, merge and sync, etc).
- virtual void OnUserCancelledDialog();
-
- // Get various information for displaying in the user interface.
- browser_sync::SyncBackendHost::StatusSummary QuerySyncStatusSummary();
- browser_sync::SyncBackendHost::Status QueryDetailedSyncStatus();
-
- AuthErrorState GetAuthErrorState() const {
- return last_auth_error_;
- }
-
- // Displays a dialog for the user to enter GAIA credentials and attempt
- // re-authentication, and returns true if it actually opened the dialog.
- // Returns false if a dialog is already showing, an auth attempt is in
- // progress, the sync system is already authenticated, or some error
- // occurred preventing the action. We make it the duty of ProfileSyncService
- // to open the dialog to easily ensure only one is ever showing.
- bool SetupInProgress() const {
- return !IsSyncEnabledByUser() && WizardIsVisible();
- }
- bool WizardIsVisible() const { return wizard_.IsVisible(); }
- void ShowLoginDialog();
-
- // Pretty-printed strings for a given StatusSummary.
- static std::wstring BuildSyncStatusSummaryText(
- const browser_sync::SyncBackendHost::StatusSummary& summary);
-
- // Returns true if the SyncBackendHost has told us it's ready to accept
- // changes.
- // TODO(timsteele): What happens if the bookmark model is loaded, a change
- // takes place, and the backend isn't initialized yet?
- bool sync_initialized() const { return backend_initialized_; }
-
- bool UIShouldDepictAuthInProgress() const {
- return is_auth_in_progress_;
- }
-
- // A timestamp marking the last time the service observed a transition from
- // the SYNCING state to the READY state. Note that this does not reflect the
- // last time we polled the server to see if there were any changes; the
- // timestamp is only snapped when syncing takes place and we download or
- // upload some bookmark entity.
- const base::Time& last_synced_time() const { return last_synced_time_; }
-
- // Returns a user-friendly string form of last synced time (in minutes).
- std::wstring GetLastSyncedTimeString() const;
-
- // Returns the authenticated username of the sync user, or empty if none
- // exists. It will only exist if the authentication service provider (e.g
- // GAIA) has confirmed the username is authentic.
- virtual string16 GetAuthenticatedUsername() const;
-
- const std::string& last_attempted_user_email() const {
- return last_attempted_user_email_;
- }
-
- // The profile we are syncing for.
- Profile* profile() { return profile_; }
-
- // Adds/removes an observer. ProfileSyncService does not take ownership of
- // the observer.
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
- protected:
- // Call this after any of the subsystems being synced (the bookmark
- // model and the sync backend) finishes its initialization. When everything
- // is ready, this function will bootstrap the subsystems so that they are
- // initially in sync, and start forwarding changes between the two models.
- void StartProcessingChangesIfReady();
-
- // Various member accessors needed by unit tests.
- browser_sync::SyncBackendHost* backend() { return backend_.get(); }
-
- // Call this when normal operation detects that the bookmark model and the
- // syncer model are inconsistent, or similar. The ProfileSyncService will
- // try to avoid doing any work to avoid crashing or corrupting things
- // further, and will report an error status if queried.
- void SetUnrecoverableError();
-
- // Returns whether processing changes is allowed. Check this before doing
- // any model-modifying operations.
- bool ShouldPushChanges();
-
- // Starts up the backend sync components.
- void StartUp();
- // Shuts down the backend sync components.
- // |sync_disabled| indicates if syncing is being disabled or not.
- void Shutdown(bool sync_disabled);
-
- // Tests need to override this.
- virtual void InitializeBackend();
-
- // Tests need this.
- void set_model_associator(browser_sync::ModelAssociator* manager) {
- model_associator_ = manager;
- }
-
- // We keep track of the last auth error observed so we can cover up the first
- // "expected" auth failure from observers.
- // TODO(timsteele): Same as expecting_first_run_auth_needed_event_. Remove
- // this!
- AuthErrorState last_auth_error_;
-
- // Cache of the last name the client attempted to authenticate.
- std::string last_attempted_user_email_;
-
- private:
- friend class browser_sync::ModelAssociator;
- friend class ProfileSyncServiceTest;
- friend class ProfileSyncServiceTestHarness;
- friend class TestModelAssociator;
- FRIEND_TEST(ProfileSyncServiceTest, UnrecoverableErrorSuspendsService);
-
- enum MoveOrCreate {
- MOVE,
- CREATE,
- };
-
- // Initializes the various settings from the command line.
- void InitSettings();
-
- // Methods to register, load and remove preferences.
- void RegisterPreferences();
- void LoadPreferences();
- void ClearPreferences();
-
- // Treat the |index|th child of |parent| as a newly added node, and create a
- // corresponding node in the sync domain using |trans|. All properties
- // will be transferred to the new node. A node corresponding to |parent|
- // must already exist and be associated for this call to succeed. Returns
- // the ID of the just-created node, or if creation fails, kInvalidID.
- int64 CreateSyncNode(const BookmarkNode* parent,
- int index,
- sync_api::WriteTransaction* trans);
-
- // Create a bookmark node corresponding to |src| if one is not already
- // associated with |src|. Returns the node that was created or updated.
- const BookmarkNode* CreateOrUpdateBookmarkNode(
- sync_api::BaseNode* src,
- BookmarkModel* model);
-
- // Creates a bookmark node under the given parent node from the given sync
- // node. Returns the newly created node.
- const BookmarkNode* CreateBookmarkNode(
- sync_api::BaseNode* sync_node,
- const BookmarkNode* parent,
- int index) const;
-
- // Sets the favicon of the given bookmark node from the given sync node.
- // Returns whether the favicon was set in the bookmark node.
- bool SetBookmarkFavicon(sync_api::BaseNode* sync_node,
- const BookmarkNode* bookmark_node) const;
-
- // Sets the favicon of the given sync node from the given bookmark node.
- void SetSyncNodeFavicon(const BookmarkNode* bookmark_node,
- sync_api::WriteNode* sync_node) const;
-
- // Helper function to determine the appropriate insertion index of sync node
- // |node| under the Bookmark model node |parent|, to make the positions
- // match up between the two models. This presumes that the predecessor of the
- // item (in the bookmark model) has already been moved into its appropriate
- // position.
- int CalculateBookmarkModelInsertionIndex(
- const BookmarkNode* parent,
- const sync_api::BaseNode* node) const;
-
- // Helper function used to fix the position of a sync node so that it matches
- // the position of a corresponding bookmark model node. |parent| and
- // |index| identify the bookmark model position. |dst| is the node whose
- // position is to be fixed. If |operation| is CREATE, treat |dst| as an
- // uncreated node and set its position via InitByCreation(); otherwise,
- // |dst| is treated as an existing node, and its position will be set via
- // SetPosition(). |trans| is the transaction to which |dst| belongs. Returns
- // false on failure.
- bool PlaceSyncNode(MoveOrCreate operation,
- const BookmarkNode* parent,
- int index,
- sync_api::WriteTransaction* trans,
- sync_api::WriteNode* dst);
-
- // Copy properties (but not position) from |src| to |dst|.
- void UpdateSyncNodeProperties(const BookmarkNode* src,
- sync_api::WriteNode* dst);
-
- // Helper function to encode a bookmark's favicon into a PNG byte vector.
- void EncodeFavicon(const BookmarkNode* src,
- std::vector<unsigned char>* dst) const;
-
- // Remove the sync node corresponding to |node|. It shouldn't have
- // any children.
- void RemoveOneSyncNode(sync_api::WriteTransaction* trans,
- const BookmarkNode* node);
-
- // Remove all the sync nodes associated with |node| and its children.
- void RemoveSyncNodeHierarchy(const BookmarkNode* node);
-
- // Whether the sync merge warning should be shown.
- bool MergeAndSyncAcceptanceNeeded() const;
-
- // Sets the last synced time to the current time.
- void UpdateLastSyncedTime();
-
- // The profile whose data we are synchronizing.
- Profile* profile_;
-
- // TODO(ncarter): Put this in a profile, once there is UI for it.
- // This specifies where to find the sync server.
- GURL sync_service_url_;
-
- // Model assocation manager instance.
- scoped_refptr<browser_sync::ModelAssociator> model_associator_;
-
- // The last time we detected a successful transition from SYNCING state.
- // Our backend notifies us whenever we should take a new snapshot.
- base::Time last_synced_time_;
-
- // Our asynchronous backend to communicate with sync components living on
- // other threads.
- scoped_ptr<browser_sync::SyncBackendHost> backend_;
-
- // Whether the SyncBackendHost has been initialized.
- bool backend_initialized_;
-
- // Set to true when the user first enables sync, and we are waiting for
- // syncapi to give us the green light on providing credentials for the first
- // time. It is set back to false as soon as we get this message, and is
- // false all other times so we don't have to persist this value as it will
- // get initialized to false.
- // TODO(timsteele): Remove this by way of starting the wizard when enabling
- // sync *before* initializing the backend. syncapi will need to change, but
- // it means we don't have to wait for the first AuthError; if we ever get
- // one, it is actually an error and this bool isn't needed.
- bool expecting_first_run_auth_needed_event_;
-
- // Various pieces of UI query this value to determine if they should show
- // an "Authenticating.." type of message. We are the only central place
- // all auth attempts funnel through, so it makes sense to provide this.
- // As its name suggests, this should NOT be used for anything other than UI.
- bool is_auth_in_progress_;
-
- // True only after all bootstrapping has succeeded: the bookmark model is
- // loaded, the sync backend is initialized, and the two domains are
- // consistent with one another.
- bool ready_to_process_changes_;
-
- // True if an unrecoverable error (e.g. violation of an assumed invariant)
- // occurred during syncer operation. This value should be checked before
- // doing any work that might corrupt things further.
- bool unrecoverable_error_detected_;
-
- SyncSetupWizard wizard_;
-
- ObserverList<Observer> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(ProfileSyncService);
-};
-
-#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_
-
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
deleted file mode 100644
index 41f6050..0000000
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ /dev/null
@@ -1,1272 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <stack>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/string_util.h"
-#include "base/string16.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
-#include "chrome/browser/profile.h"
-#include "chrome/common/pref_service.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/model_associator.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/test/testing_profile.h"
-
-using std::vector;
-using browser_sync::ModelAssociator;
-using browser_sync::SyncBackendHost;
-
-class TestModelAssociator : public ModelAssociator {
- public:
- TestModelAssociator(ProfileSyncService* service)
- : ModelAssociator(service) {
- }
-
- virtual bool GetSyncIdForTaggedNode(const string16& tag, int64* sync_id) {
- sync_api::WriteTransaction trans(
- sync_service()->backend()->GetUserShareHandle());
- sync_api::ReadNode root(&trans);
- root.InitByRootLookup();
-
- // First, try to find a node with the title among the root's children.
- // This will be the case if we are testing model persistence, and
- // are reloading a sync repository created earlier in the test.
- for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) {
- sync_api::ReadNode child(&trans);
- if (!child.InitByIdLookup(id)) {
- NOTREACHED();
- break;
- }
- if (tag == child.GetTitle()) {
- *sync_id = id;
- return true;
- }
- id = child.GetSuccessorId();
- }
-
- sync_api::WriteNode node(&trans);
- if (!node.InitByCreation(root, NULL))
- return false;
- node.SetIsFolder(true);
- node.SetTitle(tag.c_str());
- node.SetExternalId(0);
- *sync_id = node.GetId();
- return true;
- }
-};
-
-class TestProfileSyncService : public ProfileSyncService {
- public:
- TestProfileSyncService(Profile* profile) : ProfileSyncService(profile) {
- PrefService* pref_service = profile->GetPrefs();
- if (pref_service->IsPrefRegistered(prefs::kSyncUserName))
- return;
- pref_service->RegisterStringPref(prefs::kSyncUserName, string16());
- pref_service->RegisterStringPref(prefs::kSyncLastSyncedTime, string16());
- pref_service->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, true);
- }
- virtual ~TestProfileSyncService() {
- }
-
- virtual void InitializeBackend() {
- set_model_associator(new TestModelAssociator(this));
- backend()->InitializeForTestMode(L"testuser");
- // The SyncBackend posts a task to the current loop when initialization
- // completes.
- MessageLoop::current()->Run();
- // Initialization is synchronous for test mode, so we should be good to go.
- DCHECK(sync_initialized());
- }
-
- virtual void OnBackendInitialized() {
- ProfileSyncService::OnBackendInitialized();
- MessageLoop::current()->Quit();
- }
-
- virtual bool MergeAndSyncAcceptanceNeeded() {
- // Never show the dialog.
- return false;
- }
-};
-
-// FakeServerChange constructs a list of sync_api::ChangeRecords while modifying
-// the sync model, and can pass the ChangeRecord list to a
-// sync_api::SyncObserver (i.e., the ProfileSyncService) to test the client
-// change-application behavior.
-// Tests using FakeServerChange should be careful to avoid back-references,
-// since FakeServerChange will send the edits in the order specified.
-class FakeServerChange {
- public:
- explicit FakeServerChange(sync_api::WriteTransaction* trans) : trans_(trans) {
- }
-
- // Pretend that the server told the syncer to add a bookmark object.
- int64 Add(const string16& title,
- const string16& url,
- bool is_folder,
- int64 parent_id,
- int64 predecessor_id) {
- sync_api::ReadNode parent(trans_);
- EXPECT_TRUE(parent.InitByIdLookup(parent_id));
- sync_api::WriteNode node(trans_);
- if (predecessor_id == 0) {
- EXPECT_TRUE(node.InitByCreation(parent, NULL));
- } else {
- sync_api::ReadNode predecessor(trans_);
- EXPECT_TRUE(predecessor.InitByIdLookup(predecessor_id));
- EXPECT_EQ(predecessor.GetParentId(), parent.GetId());
- EXPECT_TRUE(node.InitByCreation(parent, &predecessor));
- }
- EXPECT_EQ(node.GetPredecessorId(), predecessor_id);
- EXPECT_EQ(node.GetParentId(), parent_id);
- node.SetIsFolder(is_folder);
- node.SetTitle(title.c_str());
- if (!is_folder) {
- GURL gurl(url);
- node.SetURL(url.c_str());
- }
- sync_api::SyncManager::ChangeRecord record;
- record.action = sync_api::SyncManager::ChangeRecord::ACTION_ADD;
- record.id = node.GetId();
- changes_.push_back(record);
- return node.GetId();
- }
-
- // Add a bookmark folder.
- int64 AddFolder(const string16& title,
- int64 parent_id,
- int64 predecessor_id) {
- return Add(title, string16(), true, parent_id, predecessor_id);
- }
-
- // Add a bookmark.
- int64 AddURL(const string16& title,
- const string16& url,
- int64 parent_id,
- int64 predecessor_id) {
- return Add(title, url, false, parent_id, predecessor_id);
- }
-
- // Pretend that the server told the syncer to delete an object.
- void Delete(int64 id) {
- {
- // Delete the sync node.
- sync_api::WriteNode node(trans_);
- EXPECT_TRUE(node.InitByIdLookup(id));
- EXPECT_FALSE(node.GetFirstChildId());
- node.Remove();
- }
- {
- // Verify the deletion.
- sync_api::ReadNode node(trans_);
- EXPECT_FALSE(node.InitByIdLookup(id));
- }
-
- sync_api::SyncManager::ChangeRecord record;
- record.action = sync_api::SyncManager::ChangeRecord::ACTION_DELETE;
- record.id = id;
- // Deletions are always first in the changelist, but we can't actually do
- // WriteNode::Remove() on the node until its children are moved. So, as
- // a practical matter, users of FakeServerChange must move or delete
- // children before parents. Thus, we must insert the deletion record
- // at the front of the vector.
- changes_.insert(changes_.begin(), record);
- }
-
- // Set a new title value, and return the old value.
- string16 ModifyTitle(int64 id, const string16& new_title) {
- sync_api::WriteNode node(trans_);
- EXPECT_TRUE(node.InitByIdLookup(id));
- string16 old_title = node.GetTitle();
- node.SetTitle(new_title.c_str());
- SetModified(id);
- return old_title;
- }
-
- // Set a new URL value, and return the old value.
- // TODO(ncarter): Determine if URL modifications are even legal.
- string16 ModifyURL(int64 id, const string16& new_url) {
- sync_api::WriteNode node(trans_);
- EXPECT_TRUE(node.InitByIdLookup(id));
- EXPECT_FALSE(node.GetIsFolder());
- string16 old_url = node.GetURL();
- node.SetURL(new_url.c_str());
- SetModified(id);
- return old_url;
- }
-
- // Set a new parent and predecessor value. Return the old parent id.
- // We could return the old predecessor id, but it turns out not to be
- // very useful for assertions.
- int64 ModifyPosition(int64 id, int64 parent_id, int64 predecessor_id) {
- sync_api::ReadNode parent(trans_);
- EXPECT_TRUE(parent.InitByIdLookup(parent_id));
- sync_api::WriteNode node(trans_);
- EXPECT_TRUE(node.InitByIdLookup(id));
- int64 old_parent_id = node.GetParentId();
- if (predecessor_id == 0) {
- EXPECT_TRUE(node.SetPosition(parent, NULL));
- } else {
- sync_api::ReadNode predecessor(trans_);
- EXPECT_TRUE(predecessor.InitByIdLookup(predecessor_id));
- EXPECT_EQ(predecessor.GetParentId(), parent.GetId());
- EXPECT_TRUE(node.SetPosition(parent, &predecessor));
- }
- SetModified(id);
- return old_parent_id;
- }
-
- // Pass the fake change list to |service|.
- void ApplyPendingChanges(ProfileSyncService* service) {
- service->ApplyModelChanges(trans_, changes_.size() ? &changes_[0] : NULL,
- changes_.size());
- }
-
- const vector<sync_api::SyncManager::ChangeRecord>& changes() {
- return changes_;
- }
-
- private:
- // Helper function to push an ACTION_UPDATE record onto the back
- // of the changelist.
- void SetModified(int64 id) {
- // Coalesce multi-property edits.
- if (changes_.size() > 0 && changes_.back().id == id &&
- changes_.back().action ==
- sync_api::SyncManager::ChangeRecord::ACTION_UPDATE)
- return;
- sync_api::SyncManager::ChangeRecord record;
- record.action = sync_api::SyncManager::ChangeRecord::ACTION_UPDATE;
- record.id = id;
- changes_.push_back(record);
- }
-
- // The transaction on which everything happens.
- sync_api::WriteTransaction *trans_;
-
- // The change list we construct.
- vector<sync_api::SyncManager::ChangeRecord> changes_;
-};
-
-class ProfileSyncServiceTest : public testing::Test {
- protected:
- enum LoadOption { LOAD_FROM_STORAGE, DELETE_EXISTING_STORAGE };
- enum SaveOption { SAVE_TO_STORAGE, DONT_SAVE_TO_STORAGE };
- ProfileSyncServiceTest() : model_(NULL) {
- profile_.reset(new TestingProfile());
- profile_->set_has_history_service(true);
- }
- virtual ~ProfileSyncServiceTest() {
- // Kill the service before the profile.
- service_.reset();
- profile_.reset();
- }
-
- ModelAssociator* associator() {
- DCHECK(service_.get());
- return service_->model_associator_;
- }
-
- void StartSyncService() {
- if (!service_.get()) {
- service_.reset(new TestProfileSyncService(profile_.get()));
- service_->Initialize();
- }
- // The service may have already started sync automatically if it's already
- // enabled by user once.
- if (!service_->IsSyncEnabledByUser())
- service_->EnableForUser();
- }
- void StopSyncService(SaveOption save) {
- if (save == DONT_SAVE_TO_STORAGE)
- service_->DisableForUser();
- service_.reset();
- }
-
- // Load (or re-load) the bookmark model. |load| controls use of the
- // bookmarks file on disk. |save| controls whether the newly loaded
- // bookmark model will write out a bookmark file as it goes.
- void LoadBookmarkModel(LoadOption load, SaveOption save) {
- bool delete_bookmarks = load == DELETE_EXISTING_STORAGE;
- profile_->CreateBookmarkModel(delete_bookmarks);
- model_ = profile_->GetBookmarkModel();
- // Wait for the bookmarks model to load.
- profile_->BlockUntilBookmarkModelLoaded();
- // This noticeably speeds up the unit tests that request it.
- if (save == DONT_SAVE_TO_STORAGE)
- model_->ClearStore();
- }
-
- void ExpectSyncerNodeMatching(sync_api::BaseTransaction* trans,
- const BookmarkNode* bnode) {
- sync_api::ReadNode gnode(trans);
- EXPECT_TRUE(associator()->InitSyncNodeFromBookmarkId(bnode->id(), &gnode));
- // Non-root node titles and parents must match.
- if (bnode != model_->GetBookmarkBarNode() &&
- bnode != model_->other_node()) {
- EXPECT_EQ(bnode->GetTitle(), gnode.GetTitle());
- EXPECT_EQ(associator()->GetBookmarkNodeFromSyncId(gnode.GetParentId()),
- bnode->GetParent());
- }
- EXPECT_EQ(bnode->is_folder(), gnode.GetIsFolder());
- if (bnode->is_url())
- EXPECT_EQ(bnode->GetURL(), GURL(gnode.GetURL()));
-
- // Check for position matches.
- int browser_index = bnode->GetParent()->IndexOfChild(bnode);
- if (browser_index == 0) {
- EXPECT_EQ(gnode.GetPredecessorId(), 0);
- } else {
- const BookmarkNode* bprev =
- bnode->GetParent()->GetChild(browser_index - 1);
- sync_api::ReadNode gprev(trans);
- ASSERT_TRUE(associator()->InitSyncNodeFromBookmarkId(bprev->id(),
- &gprev));
- EXPECT_EQ(gnode.GetPredecessorId(), gprev.GetId());
- EXPECT_EQ(gnode.GetParentId(), gprev.GetParentId());
- }
- if (browser_index == bnode->GetParent()->GetChildCount() - 1) {
- EXPECT_EQ(gnode.GetSuccessorId(), 0);
- } else {
- const BookmarkNode* bnext =
- bnode->GetParent()->GetChild(browser_index + 1);
- sync_api::ReadNode gnext(trans);
- ASSERT_TRUE(associator()->InitSyncNodeFromBookmarkId(bnext->id(),
- &gnext));
- EXPECT_EQ(gnode.GetSuccessorId(), gnext.GetId());
- EXPECT_EQ(gnode.GetParentId(), gnext.GetParentId());
- }
- if (bnode->GetChildCount()) {
- EXPECT_TRUE(gnode.GetFirstChildId());
- }
- }
-
- void ExpectSyncerNodeMatching(const BookmarkNode* bnode) {
- sync_api::ReadTransaction trans(service_->backend_->GetUserShareHandle());
- ExpectSyncerNodeMatching(&trans, bnode);
- }
-
- void ExpectBrowserNodeMatching(sync_api::BaseTransaction* trans,
- int64 sync_id) {
- EXPECT_TRUE(sync_id);
- const BookmarkNode* bnode =
- associator()->GetBookmarkNodeFromSyncId(sync_id);
- ASSERT_TRUE(bnode);
- int64 id = associator()->GetSyncIdFromBookmarkId(bnode->id());
- EXPECT_EQ(id, sync_id);
- ExpectSyncerNodeMatching(trans, bnode);
- }
-
- void ExpectBrowserNodeUnknown(int64 sync_id) {
- EXPECT_FALSE(associator()->GetBookmarkNodeFromSyncId(sync_id));
- }
-
- void ExpectBrowserNodeKnown(int64 sync_id) {
- EXPECT_TRUE(associator()->GetBookmarkNodeFromSyncId(sync_id));
- }
-
- void ExpectSyncerNodeKnown(const BookmarkNode* node) {
- int64 sync_id = associator()->GetSyncIdFromBookmarkId(node->id());
- EXPECT_NE(sync_id, sync_api::kInvalidId);
- }
-
- void ExpectSyncerNodeUnknown(const BookmarkNode* node) {
- int64 sync_id = associator()->GetSyncIdFromBookmarkId(node->id());
- EXPECT_EQ(sync_id, sync_api::kInvalidId);
- }
-
- void ExpectBrowserNodeTitle(int64 sync_id, const string16& title) {
- const BookmarkNode* bnode =
- associator()->GetBookmarkNodeFromSyncId(sync_id);
- ASSERT_TRUE(bnode);
- EXPECT_EQ(bnode->GetTitle(), title);
- }
-
- void ExpectBrowserNodeURL(int64 sync_id, const string16& url) {
- const BookmarkNode* bnode =
- associator()->GetBookmarkNodeFromSyncId(sync_id);
- ASSERT_TRUE(bnode);
- GURL url2(url);
- EXPECT_EQ(url2, bnode->GetURL());
- }
-
- void ExpectBrowserNodeParent(int64 sync_id, int64 parent_sync_id) {
- const BookmarkNode* node = associator()->GetBookmarkNodeFromSyncId(sync_id);
- ASSERT_TRUE(node);
- const BookmarkNode* parent =
- associator()->GetBookmarkNodeFromSyncId(parent_sync_id);
- EXPECT_TRUE(parent);
- EXPECT_EQ(node->GetParent(), parent);
- }
-
- void ExpectModelMatch(sync_api::BaseTransaction* trans) {
- const BookmarkNode* root = model_->root_node();
- EXPECT_EQ(root->IndexOfChild(model_->GetBookmarkBarNode()), 0);
- EXPECT_EQ(root->IndexOfChild(model_->other_node()), 1);
-
- std::stack<int64> stack;
- stack.push(bookmark_bar_id());
- while (!stack.empty()) {
- int64 id = stack.top();
- stack.pop();
- if (!id) continue;
-
- ExpectBrowserNodeMatching(trans, id);
-
- sync_api::ReadNode gnode(trans);
- ASSERT_TRUE(gnode.InitByIdLookup(id));
- stack.push(gnode.GetFirstChildId());
- stack.push(gnode.GetSuccessorId());
- }
- }
-
- void ExpectModelMatch() {
- sync_api::ReadTransaction trans(service_->backend_->GetUserShareHandle());
- ExpectModelMatch(&trans);
- }
-
- int64 other_bookmarks_id() {
- return associator()->GetSyncIdFromBookmarkId(model_->other_node()->id());
- }
-
- int64 bookmark_bar_id() {
- return associator()->GetSyncIdFromBookmarkId(
- model_->GetBookmarkBarNode()->id());
- }
-
- SyncBackendHost* backend() { return service_->backend_.get(); }
-
- // This serves as the "UI loop" on which the ProfileSyncService lives and
- // operates. It is needed because the SyncBackend can post tasks back to
- // the service, meaning it can't be null. It doesn't have to be running,
- // though -- OnInitializationCompleted is the only example (so far) in this
- // test where we need to Run the loop to swallow a task and then quit, to
- // avoid leaking the ProfileSyncService (the PostTask will retain the callee
- // and caller until the task is run).
- MessageLoop message_loop_;
-
- scoped_ptr<ProfileSyncService> service_;
- scoped_ptr<TestingProfile> profile_;
- BookmarkModel* model_;
-};
-
-TEST_F(ProfileSyncServiceTest, InitialState) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- EXPECT_TRUE(other_bookmarks_id());
- EXPECT_TRUE(bookmark_bar_id());
-
- ExpectModelMatch();
-}
-
-TEST_F(ProfileSyncServiceTest, BookmarkModelOperations) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- // Test addition.
- const BookmarkNode* folder =
- model_->AddGroup(model_->other_node(), 0, L"foobar");
- ExpectSyncerNodeMatching(folder);
- ExpectModelMatch();
- const BookmarkNode* folder2 = model_->AddGroup(folder, 0, L"nested");
- ExpectSyncerNodeMatching(folder2);
- ExpectModelMatch();
- const BookmarkNode* url1 = model_->AddURL(
- folder, 0, L"Internets #1 Pies Site", GURL(L"http://www.easypie.com/"));
- ExpectSyncerNodeMatching(url1);
- ExpectModelMatch();
- const BookmarkNode* url2 = model_->AddURL(
- folder, 1, L"Airplanes", GURL(L"http://www.easyjet.com/"));
- ExpectSyncerNodeMatching(url2);
- ExpectModelMatch();
-
- // Test modification.
- model_->SetTitle(url2, L"EasyJet");
- ExpectModelMatch();
- model_->Move(url1, folder2, 0);
- ExpectModelMatch();
- model_->Move(folder2, model_->GetBookmarkBarNode(), 0);
- ExpectModelMatch();
- model_->SetTitle(folder2, L"Not Nested");
- ExpectModelMatch();
- model_->Move(folder, folder2, 0);
- ExpectModelMatch();
- model_->SetTitle(folder, L"who's nested now?");
- ExpectModelMatch();
-
- // Test deletion.
- // Delete a single item.
- model_->Remove(url2->GetParent(), url2->GetParent()->IndexOfChild(url2));
- ExpectModelMatch();
- // Delete an item with several children.
- model_->Remove(folder2->GetParent(),
- folder2->GetParent()->IndexOfChild(folder2));
- ExpectModelMatch();
-}
-
-TEST_F(ProfileSyncServiceTest, ServerChangeProcessing) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
-
- FakeServerChange adds(&trans);
- int64 f1 = adds.AddFolder(L"Server Folder B", bookmark_bar_id(), 0);
- int64 f2 = adds.AddFolder(L"Server Folder A", bookmark_bar_id(), f1);
- int64 u1 = adds.AddURL(L"Some old site", L"ftp://nifty.andrew.cmu.edu/",
- bookmark_bar_id(), f2);
- int64 u2 = adds.AddURL(L"Nifty", L"ftp://nifty.andrew.cmu.edu/", f1, 0);
- // u3 is a duplicate URL
- int64 u3 = adds.AddURL(L"Nifty2", L"ftp://nifty.andrew.cmu.edu/", f1, u2);
- // u4 is a duplicate title, different URL.
- int64 u4 = adds.AddURL(L"Some old site", L"http://slog.thestranger.com/",
- bookmark_bar_id(), u1);
- // u5 tests an empty-string title.
- string16 javascript_url(L"javascript:(function(){var w=window.open(" \
- L"'about:blank','gnotesWin','location=0,menubar=0," \
- L"scrollbars=0,status=0,toolbar=0,width=300," \
- L"height=300,resizable');});");
- int64 u5 = adds.AddURL(L"", javascript_url, other_bookmarks_id(), 0);
-
- vector<sync_api::SyncManager::ChangeRecord>::const_iterator it;
- // The bookmark model shouldn't yet have seen any of the nodes of |adds|.
- for (it = adds.changes().begin(); it != adds.changes().end(); ++it)
- ExpectBrowserNodeUnknown(it->id);
-
- adds.ApplyPendingChanges(service_.get());
-
- // Make sure the bookmark model received all of the nodes in |adds|.
- for (it = adds.changes().begin(); it != adds.changes().end(); ++it)
- ExpectBrowserNodeMatching(&trans, it->id);
- ExpectModelMatch(&trans);
-
- // Part two: test modifications.
- FakeServerChange mods(&trans);
- // Mess with u2, and move it into empty folder f2
- // TODO(ncarter): Determine if we allow ModifyURL ops or not.
- /* string16 u2_old_url = mods.ModifyURL(u2, L"http://www.google.com"); */
- string16 u2_old_title = mods.ModifyTitle(u2, L"The Google");
- int64 u2_old_parent = mods.ModifyPosition(u2, f2, 0);
-
- // Now move f1 after u2.
- string16 f1_old_title = mods.ModifyTitle(f1, L"Server Folder C");
- int64 f1_old_parent = mods.ModifyPosition(f1, f2, u2);
-
- // Then add u3 after f1.
- int64 u3_old_parent = mods.ModifyPosition(u3, f2, f1);
-
- // Test that the property changes have not yet taken effect.
- ExpectBrowserNodeTitle(u2, u2_old_title);
- /* ExpectBrowserNodeURL(u2, u2_old_url); */
- ExpectBrowserNodeParent(u2, u2_old_parent);
-
- ExpectBrowserNodeTitle(f1, f1_old_title);
- ExpectBrowserNodeParent(f1, f1_old_parent);
-
- ExpectBrowserNodeParent(u3, u3_old_parent);
-
- // Apply the changes.
- mods.ApplyPendingChanges(service_.get());
-
- // Check for successful application.
- for (it = mods.changes().begin(); it != mods.changes().end(); ++it)
- ExpectBrowserNodeMatching(&trans, it->id);
- ExpectModelMatch(&trans);
-
- // Part 3: Test URL deletion.
- FakeServerChange dels(&trans);
- dels.Delete(u2);
- dels.Delete(u3);
-
- ExpectBrowserNodeKnown(u2);
- ExpectBrowserNodeKnown(u3);
-
- dels.ApplyPendingChanges(service_.get());
-
- ExpectBrowserNodeUnknown(u2);
- ExpectBrowserNodeUnknown(u3);
- ExpectModelMatch(&trans);
-}
-
-// Tests a specific case in ApplyModelChanges where we move the
-// children out from under a parent, and then delete the parent
-// in the same changelist. The delete shows up first in the changelist,
-// requiring the children to be moved to a temporary location.
-TEST_F(ProfileSyncServiceTest, ServerChangeRequiringFosterParent) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
-
- // Stress the immediate children of other_node because that's where
- // ApplyModelChanges puts a temporary foster parent node.
- string16 url(L"http://dev.chromium.org/");
- FakeServerChange adds(&trans);
- int64 f0 = other_bookmarks_id(); // + other_node
- int64 f1 = adds.AddFolder(L"f1", f0, 0); // + f1
- int64 f2 = adds.AddFolder(L"f2", f1, 0); // + f2
- int64 u3 = adds.AddURL( L"u3", url, f2, 0); // + u3
- int64 u4 = adds.AddURL( L"u4", url, f2, u3); // + u4
- int64 u5 = adds.AddURL( L"u5", url, f1, f2); // + u5
- int64 f6 = adds.AddFolder(L"f6", f1, u5); // + f6
- int64 u7 = adds.AddURL( L"u7", url, f0, f1); // + u7
-
- vector<sync_api::SyncManager::ChangeRecord>::const_iterator it;
- // The bookmark model shouldn't yet have seen any of the nodes of |adds|.
- for (it = adds.changes().begin(); it != adds.changes().end(); ++it)
- ExpectBrowserNodeUnknown(it->id);
-
- adds.ApplyPendingChanges(service_.get());
-
- // Make sure the bookmark model received all of the nodes in |adds|.
- for (it = adds.changes().begin(); it != adds.changes().end(); ++it)
- ExpectBrowserNodeMatching(&trans, it->id);
- ExpectModelMatch(&trans);
-
- // We have to do the moves before the deletions, but FakeServerChange will
- // put the deletion at the front of the changelist.
- FakeServerChange ops(&trans);
- ops.ModifyPosition(f6, other_bookmarks_id(), 0);
- ops.ModifyPosition(u3, other_bookmarks_id(), f1); // Prev == f1 is OK here.
- ops.ModifyPosition(f2, other_bookmarks_id(), u7);
- ops.ModifyPosition(u7, f2, 0);
- ops.ModifyPosition(u4, other_bookmarks_id(), f2);
- ops.ModifyPosition(u5, f6, 0);
- ops.Delete(f1);
-
- ops.ApplyPendingChanges(service_.get());
-
- ExpectModelMatch(&trans);
-}
-
-// Simulate a server change record containing a valid but non-canonical URL.
-TEST_F(ProfileSyncServiceTest, ServerChangeWithNonCanonicalURL) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- {
- sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
-
- FakeServerChange adds(&trans);
- std::string url("http://dev.chromium.org");
- EXPECT_NE(GURL(url).spec(), url);
- int64 u1 = adds.AddURL(L"u1", UTF8ToWide(url), other_bookmarks_id(), 0);
-
- adds.ApplyPendingChanges(service_.get());
-
- EXPECT_TRUE(model_->other_node()->GetChildCount() == 1);
- ExpectModelMatch(&trans);
- }
-
- // Now reboot the sync service, forcing a merge step.
- StopSyncService(SAVE_TO_STORAGE);
- LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- // There should still be just the one bookmark.
- EXPECT_TRUE(model_->other_node()->GetChildCount() == 1);
- ExpectModelMatch();
-}
-
-// Simulate a server change record containing an invalid URL (per GURL).
-// TODO(ncarter): Disabled due to crashes. Fix bug 1677563.
-TEST_F(ProfileSyncServiceTest, DISABLED_ServerChangeWithInvalidURL) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- int child_count = 0;
- {
- sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
-
- FakeServerChange adds(&trans);
- EXPECT_FALSE(GURL("x").is_valid());
- int64 u1 = adds.AddURL(L"u1", L"x", other_bookmarks_id(), 0);
-
- adds.ApplyPendingChanges(service_.get());
-
- // We're lenient about what should happen -- the model could wind up with
- // the node or without it; but things should be consistent, and we
- // shouldn't crash.
- child_count = model_->other_node()->GetChildCount();
- EXPECT_TRUE(child_count == 0 || child_count == 1);
- ExpectModelMatch(&trans);
- }
-
- // Now reboot the sync service, forcing a merge step.
- StopSyncService(SAVE_TO_STORAGE);
- LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- // Things ought not to have changed.
- EXPECT_EQ(model_->other_node()->GetChildCount(), child_count);
- ExpectModelMatch();
-}
-
-// Test strings that might pose a problem if the titles ever became used as
-// file names in the sync backend.
-TEST_F(ProfileSyncServiceTest, CornerCaseNames) {
- // TODO(ncarter): Bug 1570238 explains the failure of this test.
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- char16* names[] = {
- // The empty string.
- L"",
- // Illegal Windows filenames.
- L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4",
- L"COM5", L"COM6", L"COM7", L"COM8", L"COM9", L"LPT1", L"LPT2", L"LPT3",
- L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9",
- // Current/parent directory markers.
- L".", L"..", L"...",
- // Files created automatically by the Windows shell.
- L"Thumbs.db", L".DS_Store",
- // Names including Win32-illegal characters, and path separators.
- L"foo/bar", L"foo\\bar", L"foo?bar", L"foo:bar", L"foo|bar", L"foo\"bar",
- L"foo'bar", L"foo<bar", L"foo>bar", L"foo%bar", L"foo*bar", L"foo]bar",
- L"foo[bar",
- };
- // Create both folders and bookmarks using each name.
- GURL url("http://www.doublemint.com");
- for (int i = 0; i < arraysize(names); ++i) {
- model_->AddGroup(model_->other_node(), 0, names[i]);
- model_->AddURL(model_->other_node(), 0, names[i], url);
- }
-
- // Verify that the browser model matches the sync model.
- EXPECT_EQ(model_->other_node()->GetChildCount(), 2*arraysize(names));
- ExpectModelMatch();
-}
-
-// Stress the internal representation of position by sparse numbers. We want
-// to repeatedly bisect the range of available positions, to force the
-// syncer code to renumber its ranges. Pick a number big enough so that it
-// would exhaust 32bits of room between items a couple of times.
-TEST_F(ProfileSyncServiceTest, RepeatedMiddleInsertion) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- static const int kTimesToInsert = 256;
-
- // Create two book-end nodes to insert between.
- model_->AddGroup(model_->other_node(), 0, L"Alpha");
- model_->AddGroup(model_->other_node(), 1, L"Omega");
- int count = 2;
-
- // Test insertion in first half of range by repeatedly inserting in second
- // position.
- for (int i = 0; i < kTimesToInsert; ++i) {
- string16 title = string16(L"Pre-insertion ") + IntToWString(i);
- model_->AddGroup(model_->other_node(), 1, title);
- count++;
- }
-
- // Test insertion in second half of range by repeatedly inserting in
- // second-to-last position.
- for (int i = 0; i < kTimesToInsert; ++i) {
- string16 title = string16(L"Post-insertion ") + IntToWString(i);
- model_->AddGroup(model_->other_node(), count - 1, title);
- count++;
- }
-
- // Verify that the browser model matches the sync model.
- EXPECT_EQ(model_->other_node()->GetChildCount(), count);
- ExpectModelMatch();
-}
-
-// Introduce a consistency violation into the model, and see that it
-// puts itself into a lame, error state.
-TEST_F(ProfileSyncServiceTest, UnrecoverableErrorSuspendsService) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- // Synchronization should be up and running at this point.
- EXPECT_TRUE(service_->ShouldPushChanges());
-
- // Add a node which will be the target of the consistency violation.
- const BookmarkNode* node =
- model_->AddGroup(model_->other_node(), 0, L"node");
- ExpectSyncerNodeMatching(node);
-
- // Now destroy the syncer node as if we were the ProfileSyncService without
- // updating the ProfileSyncService state. This should introduce
- // inconsistency between the two models.
- {
- sync_api::WriteTransaction trans(service_->backend_->GetUserShareHandle());
- sync_api::WriteNode sync_node(&trans);
- EXPECT_TRUE(associator()->InitSyncNodeFromBookmarkId(node->id(),
- &sync_node));
- sync_node.Remove();
- }
- // The models don't match at this point, but the ProfileSyncService
- // doesn't know it yet.
- ExpectSyncerNodeKnown(node);
- EXPECT_TRUE(service_->ShouldPushChanges());
-
- // Add a child to the inconsistent node. This should cause detection of the
- // problem.
- const BookmarkNode* nested = model_->AddGroup(node, 0, L"nested");
- EXPECT_FALSE(service_->ShouldPushChanges());
- ExpectSyncerNodeUnknown(nested);
-
- // Try to add a node under a totally different parent. This should also
- // fail -- the ProfileSyncService should stop processing changes after
- // encountering a consistency violation.
- const BookmarkNode* unrelated = model_->AddGroup(
- model_->GetBookmarkBarNode(), 0, L"unrelated");
- EXPECT_FALSE(service_->ShouldPushChanges());
- ExpectSyncerNodeUnknown(unrelated);
-
- // TODO(ncarter): We ought to test the ProfileSyncService state machine
- // directly here once that's formalized and exposed.
-}
-
-struct TestData {
- const char16* title;
- const char16* url;
-};
-
-// TODO(ncarter): Integrate the existing TestNode/PopulateNodeFromString code
-// in the bookmark model unittest, to make it simpler to set up test data
-// here (and reduce the amount of duplication among tests), and to reduce the
-// duplication.
-class ProfileSyncServiceTestWithData : public ProfileSyncServiceTest {
- protected:
- // Populates or compares children of the given bookmark node from/with the
- // given test data array with the given size.
- void PopulateFromTestData(const BookmarkNode* node,
- const TestData* data,
- int size);
- void CompareWithTestData(const BookmarkNode* node,
- const TestData* data,
- int size);
-
- void ExpectBookmarkModelMatchesTestData();
- void WriteTestDataToBookmarkModel();
-};
-
-namespace {
-
-// Constants for bookmark model that looks like:
-// |-- Bookmark bar
-// | |-- u2, http://www.u2.com/
-// | |-- f1
-// | | |-- f1u4, http://www.f1u4.com/
-// | | |-- f1u2, http://www.f1u2.com/
-// | | |-- f1u3, http://www.f1u3.com/
-// | | +-- f1u1, http://www.f1u1.com/
-// | |-- u1, http://www.u1.com/
-// | +-- f2
-// | |-- f2u2, http://www.f2u2.com/
-// | |-- f2u4, http://www.f2u4.com/
-// | |-- f2u3, http://www.f2u3.com/
-// | +-- f2u1, http://www.f2u1.com/
-// +-- Other bookmarks
-// |-- f3
-// | |-- f3u4, http://www.f3u4.com/
-// | |-- f3u2, http://www.f3u2.com/
-// | |-- f3u3, http://www.f3u3.com/
-// | +-- f3u1, http://www.f3u1.com/
-// |-- u4, http://www.u4.com/
-// |-- u3, http://www.u3.com/
-// --- f4
-// | |-- f4u1, http://www.f4u1.com/
-// | |-- f4u2, http://www.f4u2.com/
-// | |-- f4u3, http://www.f4u3.com/
-// | +-- f4u4, http://www.f4u4.com/
-// |-- dup
-// | +-- dupu1, http://www.dupu1.com/
-// +-- dup
-// +-- dupu2, http://www.dupu1.com/
-//
-static TestData kBookmarkBarChildren[] = {
- { L"u2", L"http://www.u2.com/" },
- { L"f1", NULL },
- { L"u1", L"http://www.u1.com/" },
- { L"f2", NULL },
-};
-static TestData kF1Children[] = {
- { L"f1u4", L"http://www.f1u4.com/" },
- { L"f1u2", L"http://www.f1u2.com/" },
- { L"f1u3", L"http://www.f1u3.com/" },
- { L"f1u1", L"http://www.f1u1.com/" },
-};
-static TestData kF2Children[] = {
- { L"f2u2", L"http://www.f2u2.com/" },
- { L"f2u4", L"http://www.f2u4.com/" },
- { L"f2u3", L"http://www.f2u3.com/" },
- { L"f2u1", L"http://www.f2u1.com/" },
-};
-
-static TestData kOtherBookmarksChildren[] = {
- { L"f3", NULL },
- { L"u4", L"http://www.u4.com/" },
- { L"u3", L"http://www.u3.com/" },
- { L"f4", NULL },
- { L"dup", NULL },
- { L"dup", NULL },
-};
-static TestData kF3Children[] = {
- { L"f3u4", L"http://www.f3u4.com/" },
- { L"f3u2", L"http://www.f3u2.com/" },
- { L"f3u3", L"http://www.f3u3.com/" },
- { L"f3u1", L"http://www.f3u1.com/" },
-};
-static TestData kF4Children[] = {
- { L"f4u1", L"http://www.f4u1.com/" },
- { L"f4u2", L"http://www.f4u2.com/" },
- { L"f4u3", L"http://www.f4u3.com/" },
- { L"f4u4", L"http://www.f4u4.com/" },
-};
-static TestData kDup1Children[] = {
- { L"dupu1", L"http://www.dupu1.com/" },
-};
-static TestData kDup2Children[] = {
- { L"dupu2", L"http://www.dupu2.com/" },
-};
-
-} // anonymous namespace.
-
-void ProfileSyncServiceTestWithData::PopulateFromTestData(
- const BookmarkNode* node, const TestData* data, int size) {
- DCHECK(node);
- DCHECK(data);
- DCHECK(node->is_folder());
- for (int i = 0; i < size; ++i) {
- const TestData& item = data[i];
- if (item.url) {
- model_->AddURL(node, i, item.title, GURL(item.url));
- } else {
- model_->AddGroup(node, i, item.title);
- }
- }
-}
-
-void ProfileSyncServiceTestWithData::CompareWithTestData(
- const BookmarkNode* node, const TestData* data, int size) {
- DCHECK(node);
- DCHECK(data);
- DCHECK(node->is_folder());
- for (int i = 0; i < size; ++i) {
- const BookmarkNode* child_node = node->GetChild(i);
- const TestData& item = data[i];
- EXPECT_TRUE(child_node->GetTitle() == item.title);
- if (item.url) {
- EXPECT_FALSE(child_node->is_folder());
- EXPECT_TRUE(child_node->is_url());
- EXPECT_TRUE(child_node->GetURL() == GURL(item.url));
- } else {
- EXPECT_TRUE(child_node->is_folder());
- EXPECT_FALSE(child_node->is_url());
- }
- }
-}
-
-// TODO(munjal): We should implement some way of generating random data and can
-// use the same seed to generate the same sequence.
-void ProfileSyncServiceTestWithData::WriteTestDataToBookmarkModel() {
- const BookmarkNode* bookmarks_bar_node = model_->GetBookmarkBarNode();
- PopulateFromTestData(bookmarks_bar_node,
- kBookmarkBarChildren,
- arraysize(kBookmarkBarChildren));
-
- ASSERT_GE(bookmarks_bar_node->GetChildCount(), 4);
- const BookmarkNode* f1_node = bookmarks_bar_node->GetChild(1);
- PopulateFromTestData(f1_node, kF1Children, arraysize(kF1Children));
- const BookmarkNode* f2_node = bookmarks_bar_node->GetChild(3);
- PopulateFromTestData(f2_node, kF2Children, arraysize(kF2Children));
-
- const BookmarkNode* other_bookmarks_node = model_->other_node();
- PopulateFromTestData(other_bookmarks_node,
- kOtherBookmarksChildren,
- arraysize(kOtherBookmarksChildren));
-
- ASSERT_GE(other_bookmarks_node->GetChildCount(), 6);
- const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0);
- PopulateFromTestData(f3_node, kF3Children, arraysize(kF3Children));
- const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3);
- PopulateFromTestData(f4_node, kF4Children, arraysize(kF4Children));
- const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4);
- PopulateFromTestData(dup_node, kDup1Children, arraysize(kDup1Children));
- dup_node = other_bookmarks_node->GetChild(5);
- PopulateFromTestData(dup_node, kDup2Children, arraysize(kDup2Children));
-
- ExpectBookmarkModelMatchesTestData();
-}
-
-void ProfileSyncServiceTestWithData::ExpectBookmarkModelMatchesTestData() {
- const BookmarkNode* bookmark_bar_node = model_->GetBookmarkBarNode();
- CompareWithTestData(bookmark_bar_node,
- kBookmarkBarChildren,
- arraysize(kBookmarkBarChildren));
-
- ASSERT_GE(bookmark_bar_node->GetChildCount(), 4);
- const BookmarkNode* f1_node = bookmark_bar_node->GetChild(1);
- CompareWithTestData(f1_node, kF1Children, arraysize(kF1Children));
- const BookmarkNode* f2_node = bookmark_bar_node->GetChild(3);
- CompareWithTestData(f2_node, kF2Children, arraysize(kF2Children));
-
- const BookmarkNode* other_bookmarks_node = model_->other_node();
- CompareWithTestData(other_bookmarks_node,
- kOtherBookmarksChildren,
- arraysize(kOtherBookmarksChildren));
-
- ASSERT_GE(other_bookmarks_node->GetChildCount(), 6);
- const BookmarkNode* f3_node = other_bookmarks_node->GetChild(0);
- CompareWithTestData(f3_node, kF3Children, arraysize(kF3Children));
- const BookmarkNode* f4_node = other_bookmarks_node->GetChild(3);
- CompareWithTestData(f4_node, kF4Children, arraysize(kF4Children));
- const BookmarkNode* dup_node = other_bookmarks_node->GetChild(4);
- CompareWithTestData(dup_node, kDup1Children, arraysize(kDup1Children));
- dup_node = other_bookmarks_node->GetChild(5);
- CompareWithTestData(dup_node, kDup2Children, arraysize(kDup2Children));
-}
-
-// Tests persistence of the profile sync service by destroying the
-// profile sync service and then reloading it from disk.
-TEST_F(ProfileSyncServiceTestWithData, Persistence) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- WriteTestDataToBookmarkModel();
-
- ExpectModelMatch();
-
- // Force both models to discard their data and reload from disk. This
- // simulates what would happen if the browser were to shutdown normally,
- // and then relaunch.
- StopSyncService(SAVE_TO_STORAGE);
- LoadBookmarkModel(LOAD_FROM_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- ExpectBookmarkModelMatchesTestData();
-
- // With the BookmarkModel contents verified, ExpectModelMatch will
- // verify the contents of the sync model.
- ExpectModelMatch();
-}
-
-// Tests the merge case when the BookmarkModel is non-empty but the
-// sync model is empty. This corresponds to uploading browser
-// bookmarks to an initially empty, new account.
-TEST_F(ProfileSyncServiceTestWithData, MergeWithEmptySyncModel) {
- // Don't start the sync service until we've populated the bookmark model.
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
-
- WriteTestDataToBookmarkModel();
-
- // Restart the profile sync service. This should trigger a merge step
- // during initialization -- we expect the browser bookmarks to be written
- // to the sync service during this call.
- StartSyncService();
-
- // Verify that the bookmark model hasn't changed, and that the sync model
- // matches it exactly.
- ExpectBookmarkModelMatchesTestData();
- ExpectModelMatch();
-}
-
-// Tests the merge case when the BookmarkModel is empty but the sync model is
-// non-empty. This corresponds (somewhat) to a clean install of the browser,
-// with no bookmarks, connecting to a sync account that has some bookmarks.
-TEST_F(ProfileSyncServiceTestWithData, MergeWithEmptyBookmarkModel) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- WriteTestDataToBookmarkModel();
-
- ExpectModelMatch();
-
- // Force the sync service to shut down and write itself to disk.
- StopSyncService(SAVE_TO_STORAGE);
-
- // Blow away the bookmark model -- it should be empty afterwards.
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- EXPECT_EQ(model_->GetBookmarkBarNode()->GetChildCount(), 0);
- EXPECT_EQ(model_->other_node()->GetChildCount(), 0);
-
- // Now restart the sync service. Starting it should populate the bookmark
- // model -- test for consistency.
- StartSyncService();
- ExpectBookmarkModelMatchesTestData();
- ExpectModelMatch();
-}
-
-// Tests the merge cases when both the models are expected to be identical
-// after the merge.
-TEST_F(ProfileSyncServiceTestWithData, MergeExpectedIdenticalModels) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
- WriteTestDataToBookmarkModel();
- ExpectModelMatch();
- StopSyncService(SAVE_TO_STORAGE);
-
- // At this point both the bookmark model and the server should have the
- // exact same data and it should match the test data.
- LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
- ExpectBookmarkModelMatchesTestData();
- ExpectModelMatch();
- StopSyncService(SAVE_TO_STORAGE);
-
- // Now reorder some bookmarks in the bookmark model and then merge. Make
- // sure we get the order of the server after merge.
- LoadBookmarkModel(LOAD_FROM_STORAGE, DONT_SAVE_TO_STORAGE);
- ExpectBookmarkModelMatchesTestData();
- const BookmarkNode* bookmark_bar = model_->GetBookmarkBarNode();
- ASSERT_TRUE(bookmark_bar);
- ASSERT_GT(bookmark_bar->GetChildCount(), 1);
- model_->Move(bookmark_bar->GetChild(0), bookmark_bar, 1);
- StartSyncService();
- ExpectModelMatch();
- ExpectBookmarkModelMatchesTestData();
-}
-
-// Tests the merge cases when both the models are expected to be identical
-// after the merge.
-TEST_F(ProfileSyncServiceTestWithData, MergeModelsWithSomeExtras) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- WriteTestDataToBookmarkModel();
- ExpectBookmarkModelMatchesTestData();
-
- // Remove some nodes and reorder some nodes.
- const BookmarkNode* bookmark_bar_node = model_->GetBookmarkBarNode();
- int remove_index = 2;
- ASSERT_GT(bookmark_bar_node->GetChildCount(), remove_index);
- const BookmarkNode* child_node = bookmark_bar_node->GetChild(remove_index);
- ASSERT_TRUE(child_node);
- ASSERT_TRUE(child_node->is_url());
- model_->Remove(bookmark_bar_node, remove_index);
- ASSERT_GT(bookmark_bar_node->GetChildCount(), remove_index);
- child_node = bookmark_bar_node->GetChild(remove_index);
- ASSERT_TRUE(child_node);
- ASSERT_TRUE(child_node->is_folder());
- model_->Remove(bookmark_bar_node, remove_index);
-
- const BookmarkNode* other_node = model_->other_node();
- ASSERT_GE(other_node->GetChildCount(), 1);
- const BookmarkNode* f3_node = other_node->GetChild(0);
- ASSERT_TRUE(f3_node);
- ASSERT_TRUE(f3_node->is_folder());
- remove_index = 2;
- ASSERT_GT(f3_node->GetChildCount(), remove_index);
- model_->Remove(f3_node, remove_index);
- ASSERT_GT(f3_node->GetChildCount(), remove_index);
- model_->Remove(f3_node, remove_index);
-
- StartSyncService();
- ExpectModelMatch();
- StopSyncService(SAVE_TO_STORAGE);
-
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- WriteTestDataToBookmarkModel();
- ExpectBookmarkModelMatchesTestData();
-
- // Remove some nodes and reorder some nodes.
- bookmark_bar_node = model_->GetBookmarkBarNode();
- remove_index = 0;
- ASSERT_GT(bookmark_bar_node->GetChildCount(), remove_index);
- child_node = bookmark_bar_node->GetChild(remove_index);
- ASSERT_TRUE(child_node);
- ASSERT_TRUE(child_node->is_url());
- model_->Remove(bookmark_bar_node, remove_index);
- ASSERT_GT(bookmark_bar_node->GetChildCount(), remove_index);
- child_node = bookmark_bar_node->GetChild(remove_index);
- ASSERT_TRUE(child_node);
- ASSERT_TRUE(child_node->is_folder());
- model_->Remove(bookmark_bar_node, remove_index);
-
- ASSERT_GE(bookmark_bar_node->GetChildCount(), 2);
- model_->Move(bookmark_bar_node->GetChild(0), bookmark_bar_node, 1);
-
- other_node = model_->other_node();
- ASSERT_GE(other_node->GetChildCount(), 1);
- f3_node = other_node->GetChild(0);
- ASSERT_TRUE(f3_node);
- ASSERT_TRUE(f3_node->is_folder());
- remove_index = 0;
- ASSERT_GT(f3_node->GetChildCount(), remove_index);
- model_->Remove(f3_node, remove_index);
- ASSERT_GT(f3_node->GetChildCount(), remove_index);
- model_->Remove(f3_node, remove_index);
-
- ASSERT_GE(other_node->GetChildCount(), 4);
- model_->Move(other_node->GetChild(0), other_node, 1);
- model_->Move(other_node->GetChild(2), other_node, 3);
-
- StartSyncService();
- ExpectModelMatch();
-
- // AFter the merge, the model should match the test data.
- ExpectBookmarkModelMatchesTestData();
-}
-
-// Tests that when persisted model assocations are used, things work fine.
-TEST_F(ProfileSyncServiceTestWithData, ModelAssociationPersistence) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- WriteTestDataToBookmarkModel();
- StartSyncService();
- ExpectModelMatch();
- // Force the sync service to shut down and write itself to disk.
- StopSyncService(SAVE_TO_STORAGE);
- // Now restart the sync service. This time it should use the persistent
- // assocations.
- StartSyncService();
- ExpectModelMatch();
-}
-
-TEST_F(ProfileSyncServiceTestWithData, SortChildren) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, DONT_SAVE_TO_STORAGE);
- StartSyncService();
-
- // Write test data to bookmark model and verify that the models match.
- WriteTestDataToBookmarkModel();
- const BookmarkNode* folder_added = model_->other_node()->GetChild(0);
- ASSERT_TRUE(folder_added);
- ASSERT_TRUE(folder_added->is_folder());
-
- ExpectModelMatch();
-
- // Sort the other-bookmarks children and expect that hte models match.
- model_->SortChildren(folder_added);
- ExpectModelMatch();
-}
-
-// See what happens if we enable sync but then delete the "Sync Data"
-// folder.
-TEST_F(ProfileSyncServiceTestWithData, RecoverAfterDeletingSyncDataDirectory) {
- LoadBookmarkModel(DELETE_EXISTING_STORAGE, SAVE_TO_STORAGE);
- StartSyncService();
-
- WriteTestDataToBookmarkModel();
-
- // While the service is running.
- FilePath sync_data_directory = backend()->sync_data_folder_path();
-
- // Simulate a normal shutdown for the sync service (don't disable it for
- // the user, which would reset the preferences and delete the sync data
- // directory).
- StopSyncService(SAVE_TO_STORAGE);
-
- // Now pretend that the user has deleted this directory from the disk.
- file_util::Delete(sync_data_directory, true);
-
- // Restart the sync service.
- StartSyncService();
-
- // Make sure we're back in sync. In real life, the user would need
- // to reauthenticate before this happens, but in the test, authentication
- // is sidestepped.
- ExpectBookmarkModelMatchesTestData();
- ExpectModelMatch();
-}
-
-#endif // CHROME_PERSONALIZATION \ No newline at end of file
diff --git a/chrome/browser/sync/resources/about_sync.html b/chrome/browser/sync/resources/about_sync.html
deleted file mode 100644
index 0fbd6df..0000000
--- a/chrome/browser/sync/resources/about_sync.html
+++ /dev/null
@@ -1,165 +0,0 @@
-<html>
-</html>
-<html id="t">
-<head>
-<title>About Sync</title>
-
-<style type="text/css">
-body {
- font-size: 84%;
- font-family: Arial, Helvetica, sans-serif;
- padding: 0.75em;
- margin: 0;
- min-width: 45em;
-}
-
-h1 {
- font-size: 110%;
- font-weight: bold;
- color: #4a8ee6;
- letter-spacing: -1px;
- padding: 0;
- margin: 0;
-}
-h2 {
- font-size: 110%;
- letter-spacing: -1px;
- font-weight: normal;
- color: #4a8ee6;
- padding: 0;
- margin: 0;
- padding: 0.5em 1em;
- color: #3a75bd;
- margin-left: -38px;
- padding-left: 38px;
-
- border-top: 1px solid #3a75bd;
- padding-top: 0.5em;
-
-}
-h2:first-child {
- border-top: 0;
- padding-top: 0;
-}
-
-div#header {
- padding: 0.75em 1em;
- padding-top: 0.6em;
- padding-left: 0;
- margin-bottom: 0.75em;
- position: relative;
- overflow: hidden;
- background: #5296de;
- -webkit-background-size: 100%;
- border: 1px solid #3a75bd;
- -webkit-border-radius: 6px;
- color: white;
- text-shadow: 0 0 2px black;
-}
-div#header h1 {
- padding-left: 37px;
- margin: 0;
- display: inline;
- background: url('gear.png') 12px 60% no-repeat;
- color: white;
-}
-div#header p {
- font-size: 84%;
- font-style: italic;
- padding: 0;
- margin: 0;
- color: white;
- padding-left: 0.4em;
- display: inline;
-}
-
-table.list {
- line-height: 200%;
- border-collapse: collapse;
- font-size: 84%;
- table-layout: fixed;
-}
-table.list:not([class*='filtered']) tr:nth-child(odd) td {
- background: #eff3ff;
-}
-
-table.list td {
- padding: 0 0.5em;
- vertical-align: top;
- line-height: 1.4em;
- padding-top: 0.35em;
-}
-table.list tr td:nth-last-child(1),
-table.list tr th:nth-last-child(1) {
- padding-right: 1em;
-}
-table.list:not([class*='filtered']) .tab .name {
- padding-left: 1.5em;
-}
-
-table.list .name {
-}
-
-table.list .name div {
- height: 1.6em;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-table.list .number {
- width: 7em;
- text-align: right;
-}
-
-table.list#details tr:not([class*='firstRow']) > *:nth-child(1),
-table.list#details tr:not([class*='firstRow']) > *:nth-child(4),
-table.list#details tr.firstRow th:nth-child(1),
-table.list#details tr.firstRow th:nth-child(2) {
- border-right: 1px solid #b5c6de;
-}
-table.list#details .name {
- padding-left: 25px;
- background-position: 5px center;
- background-repeat: no-repeat;
-}
-</style>
-</head>
-<body>
- <div id='header'>
- <h1>About Sync</h1>
- <p> Sync engine diagnostic data</p>
- </div>
- <div id='content'>
- <h2> Summary </h2>
- <strong jscontent="summary"></strong>
- <br /><br /><br />
- <h2> Details </h2>
- <table class='list' id='details'>
- <tr>
- <td class='name'> Authenticated </td>
- <td class='number'>
- <div jscontent="authenticated"> </div>
- <div jsdisplay="!authenticated"
- style="color:red"
- jscontent="auth_problem"></div>
- </td>
- </tr>
- </tr>
- <tr>
- <td class='name'>Last Synced</td>
- <td class='number' jscontent="time_since_sync"> </td>
- </tr>
- <tr jsselect="details">
- <td class='name'>
- <div jscontent="stat_name"></div>
- </td>
- <td class='number'>
- <div jscontent="stat_value"></div>
- </td>
- </tr>
- </table>
- </div>
-</body>
-</html>
-
diff --git a/chrome/browser/sync/resources/close.png b/chrome/browser/sync/resources/close.png
deleted file mode 100644
index 84ff892..0000000
--- a/chrome/browser/sync/resources/close.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/sync/resources/gaia_login.html b/chrome/browser/sync/resources/gaia_login.html
deleted file mode 100644
index 17cc102..0000000
--- a/chrome/browser/sync/resources/gaia_login.html
+++ /dev/null
@@ -1,331 +0,0 @@
-<html>
-<style type="text/css"><!--
- body,td,div,p,a,font,span {font-family: arial,sans-serif;}
- body { bgcolor:"#ffffff" }
- A:link {color:#0000cc; }
- A:visited { color:#551a8b; }
- A:active { color:#ff0000; }
- .form-noindent {background-color: #ffffff; border: #C3D9FF 1px solid}
---></style>
- <head>
- <style type="text/css"><!--
- .body { margin-left: 3em;
- margin-right: 5em;
- font-family: arial,sans-serif; }
- div.errorbox-good {}
- div.errorbox-bad {}
- div.errormsg { color: red; font-size: smaller;
- font-family: arial,sans-serif;}
- font.errormsg { color: red; font-size: smaller;
- font-family: arial,sans-serif;}
- hr {
- border: 0;
- background-color:#DDDDDD;
- height: 1px;
- width: 100%;
- text-align: left;
- margin: 5px;
- }
- --></style>
- </head>
- <body dir="ltr" bgcolor="#ffffff" vlink="#666666"
- style="margin-bottom: 0" onload="initForm();">
- <table width="100%" align="center" cellpadding="1" cellspacing="1">
- <tr>
- <td valign="top"> <!-- LOGIN BOX -->
- <script>
- function gaia_setFocus() {
- var f = null;
- if (document.getElementById) {
- f = document.getElementById("gaia_loginform");
- } else if (window.gaia_loginform) {
- f = window.gaia_loginform;
- }
- if (f) {
- if (f.Email && (f.Email.value == null || f.Email.value == "")) {
- f.Email.focus();
- } else if (f.Passwd) {
- f.Passwd.focus();
- }
- }
- }
-
- function advanceThrobber() {
- var throbber = document.getElementById('throb');
- throbber.style.backgroundPositionX =
- ((parseInt(throbber.style.backgroundPositionX) - 16) % 576) + 'px';
- }
-
- function showGaiaLogin(args) {
- var throbber = document.getElementById('throbber_container');
- throbber.style.display = "none";
- var f = document.getElementById("gaia_loginform");
- if (f) {
- f.Email.value = args.user;
- }
- resetErrorVisibility();
- var t = document.getElementById("errormsg_1_Password");
- if (t) {
- t.innerHTML = "Username and password do not match. [<a href=\"http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444\">?</a>]";
- }
- if (1 == args.error) {
- setElementDisplay("errormsg_1_Password", 'table-row');
- setBlurbError();
- }
- if (3 == args.error) {
- setElementDisplay("errormsg_0_Connection", 'table-row');
- setBlurbError();
- }
- document.getElementById("signIn").disabled = false;
- gaia_setFocus();
- }
-
- function CloseDialog() {
- chrome.send("DialogClose", [""]);
- }
-
- function showGaiaSuccessAndClose() {
- document.getElementById("signIn").value = "Success!";
- setTimeout(CloseDialog, 1600);
- }
-
- function showGaiaSuccessAndSettingUp() {
- document.getElementById("signIn").value = "Setting up...";
- }
-
- function initForm() {
- setInterval(advanceThrobber, 30);
- var args = JSON.parse(chrome.dialogArguments);
- showGaiaLogin(args);
- }
-
- function sendCredentialsAndClose() {
- if (!setErrorVisibility())
- return false;
-
- var throbber = document.getElementById('throbber_container');
- throbber.style.display = "inline";
- var f = document.getElementById("gaia_loginform");
- var result = JSON.stringify({"user" : f.Email.value,
- "pass" : f.Passwd.value});
- document.getElementById("signIn").disabled = true;
- chrome.send("SubmitAuth", [result]);
- }
-
- function setElementDisplay(id, display) {
- var d = document.getElementById(id);
- if (d)
- d.style.display = display;
- }
-
- function setBlurbError() {
- var blurb = document.getElementById("top_blurb");
- blurb.innerHTML =
- '<font size="-1">Setting up Bookmarks Sync<br/><br/><b>Error signing in.</b></font>';
- }
-
- function resetErrorVisibility() {
- setElementDisplay("errormsg_0_Email", 'none');
- setElementDisplay("errormsg_0_Password", 'none');
- setElementDisplay("errormsg_1_Password", 'none');
- setElementDisplay("errormsg_0_Connection", 'none');
- }
-
- function setErrorVisibility() {
- resetErrorVisibility();
- var f = document.getElementById("gaia_loginform");
- if (null == f.Email.value || "" == f.Email.value) {
- setElementDisplay("errormsg_0_Email", 'table-row');
- setBlurbError();
- return false;
- }
- if (null == f.Passwd.value || "" == f.Passwd.value) {
- setElementDisplay("errormsg_0_Password", 'table-row');
- setBlurbError();
- return false;
- }
- return true;
- }
- </script>
-<style type="text/css"><!--
- div.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; }
- font.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif;}
---></style>
-<style type="text/css"><!--
-.gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-.gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
-.gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
-.gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-.gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-.gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-.gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; }
-.gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller;
- font-style: italic; }
---></style>
-<p id="top_blurb"> <font size="-1">
-Google Chrome can sync your bookmarks with your Google account &ndash;
-bookmarks you create on this computer will be made instantly visible on all the
-computers synced to the same account.</font></p>
-<form id="gaia_loginform" onsubmit="sendCredentialsAndClose(); return false;">
-<div id="gaia_loginbox">
-<table class="form-noindent" cellspacing="3" cellpadding="5" width="100%"
- border="0">
- <tr>
- <td valign="top" style="text-align:center" nowrap="nowrap"
- bgcolor="#e8eefa">
- <div class="loginBox">
- <table id="gaia_table" align="center" border="0" cellpadding="1"
- cellspacing="0">
- <tr>
- <td colspan="2" align="center">
- <font size="-1"> Sign in with your </font>
- <table>
- <tr>
- <td valign="top">
- <img src="google_transparent.png" alt="Google">
- </img>
- </td>
- <td valign="middle">
- <font size="+0"><b>Account</b> </font>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <script type="text/javascript"><!--
- function onPreCreateAccount() {
- return true;
- }
- function onPreLogin() {
- if (window["onlogin"] != null) {
- return onlogin();
- } else {
- return true;
- }
- }
- --></script>
- <tr>
- <td colspan="2" align="center"> </td>
- </tr>
- <tr>
- <td nowrap="nowrap">
- <div align="right">
- <span class="gaia le lbl">
- Email:
- </span>
- </div>
- </td>
- <td>
- <input type="text" name="Email" id="Email" size="18"
- value="" class='gaia le val' />
- </td>
- </tr>
- <tr>
- <td></td>
- <td align="left">
- <div class="errormsg" id="errormsg_0_Email">
- Required field cannot be left blank
- </div>
- </td>
- </tr>
- <tr>
- <td></td>
- <td align="left"> </td>
- </tr>
- <tr>
- <td align="right">
- <span class="gaia le lbl">
- Password:
- </span>
- </td>
- <td>
- <input type="password" name="Passwd" id="Passwd" size="18"
- class="gaia le val"/>
- </td>
- </tr>
- <tr>
- <td></td>
- <td align="left">
- <div class="errormsg" id="errormsg_0_Password">
- Required field cannot be left blank
- </div>
- </td>
- </tr>
- <tr>
- <td>
- </td>
- <td align="left">
- <div class="errormsg" id="errormsg_1_Password">
- </div>
- </td>
- </tr>
- <tr>
- <td>
- </td>
- <td align="left">
- <div class="errormsg" id="errormsg_0_Connection">
- Could not connect to the server
- </div>
- </td>
- </tr>
- <tr>
- <td>
- </td>
- <td align="left">
- </td>
- </tr>
- <tr>
- <td>
- </td>
- <td align="left">
- <table>
- <tr>
- <td>
- <div id="throbber_container" style="display:none">
- <div id="throb" style="background-image:url(throbber.png);
- width:16px; height:16px; background-position:0px;">
- </div>
- </div>
- </td>
- <td>
- <input id="signIn" type="button" class="gaia le button"
- name="signIn" value="Sign in"
- onclick="sendCredentialsAndClose();" />
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr id="ga-fprow">
- <td colspan="2" height="16.0" class="gaia le fpwd"
- align="center" valign="bottom">
- <a href="http://www.google.com/support/accounts/bin/answer.py?answer=48598&hl=en&fpUrl=https%3A%2F%2Fwww.google.com%2Faccounts%2FForgotPasswd%3FfpOnly%3D1%26service%3Dchromiumsync"
- target=_blank>
- I cannot access my account
- </a>
- </td>
- </tr>
- <tr>
- <td colspan="2" height="16.0" class="gaia le fpwd"
- align="center" valign="bottom">
- <a href="javascript:var popup=window.open('https%3A%5Cx2F%5Cx2Fwww.google.com%5Cx2Faccounts%5Cx2FNewAccount%3Fservice%3Dchromiumsync', 'NewAccount', 'height=870,width=870,resizable=yes,scrollbars=yes');">
- Create a Google account
- </a>
- </td>
- </tr>
- </table>
- </div>
- </td>
- </tr>
-</table>
-</div>
-</form>
-</td>
-</tr>
- </table>
- <div align="right">
- <input type="button" name="cancel" value="Cancel" onclick="CloseDialog();"/>
- </div>
- </table>
-</body>
-</html>
diff --git a/chrome/browser/sync/resources/gear.png b/chrome/browser/sync/resources/gear.png
deleted file mode 100644
index 3dce105..0000000
--- a/chrome/browser/sync/resources/gear.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/sync/resources/google_transparent.png b/chrome/browser/sync/resources/google_transparent.png
deleted file mode 100644
index 73edad4..0000000
--- a/chrome/browser/sync/resources/google_transparent.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/sync/resources/merge_and_sync.html b/chrome/browser/sync/resources/merge_and_sync.html
deleted file mode 100644
index 58a769b..0000000
--- a/chrome/browser/sync/resources/merge_and_sync.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE></TITLE>
-<style type="text/css">
- body,td,div,p,a,font,span {font-family: arial,sans-serif;}
- body { bgcolor:"#ffffff" }
-.gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
-</style>
-<script>
- function advanceThrobber() {
- var throbber = document.getElementById('throb');
- throbber.style.backgroundPositionX =
- ((parseInt(throbber.style.backgroundPositionX) - 16) % 576) + 'px';
- }
-
- function acceptMergeAndSync() {
- var throbber = document.getElementById('throbber_container');
- throbber.style.display = "inline";
- document.getElementById("acceptMerge").disabled = true;
- chrome.send("SubmitMergeAndSync", [""]);
- }
-
- function Close() {
- chrome.send("DialogClose", [""]);
- }
-
- function showMergeAndSyncDone() {
- var throbber = document.getElementById('throbber_container');
- throbber.style.display = "none";
- document.getElementById("header").innerHTML =
- "<font size='-1'><b>All done!</b></font>";
- document.getElementById("close").value = "Close";
- setTimeout(Close, 1600);
- }
-</script>
-</HEAD>
-<BODY onload="setInterval(advanceThrobber, 30);">
-<p id="header"><font size="-1"><b>Your bookmarks will be merged.</b></font></p><br />
-<img src="merge_and_sync.png" alt="Merge and sync" />
-<br />
-<p><font size="-1">
-Your existing online bookmarks will be merged with the
-bookmarks on this machine. You can use the Bookmark Manager to organize
-your bookmarks after the merge.</font></p>
-<br />
-<table align="right">
- <tr>
- <td>
- <div id="throbber_container" style="display:none">
- <div id="throb" style="background-image:url(throbber.png);
- width:16px; height:16px; background-position:0px;">
- </div>
- </div>
- </td>
- <td>
- <input id="acceptMerge" type="button" class="gaia le button" name="accept"
- value="Merge and sync"
- onclick="acceptMergeAndSync();" />
- </td>
- <td>
- <input id="close" type="button" value="Abort" onclick="Close();"/>
- </td>
- </tr>
-</table>
-</BODY>
-</HTML>
diff --git a/chrome/browser/sync/resources/merge_and_sync.png b/chrome/browser/sync/resources/merge_and_sync.png
deleted file mode 100644
index a506a34..0000000
--- a/chrome/browser/sync/resources/merge_and_sync.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/sync/resources/new_tab_personalization.html b/chrome/browser/sync/resources/new_tab_personalization.html
deleted file mode 100644
index 73cf346..0000000
--- a/chrome/browser/sync/resources/new_tab_personalization.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<html>
-<head>
-<style type="text/css">
-body {
- font-family:arial;
- background-color:white;
- font-size:80%;
- margin:0px;
-}
-.section-title {
- color:#000;
- line-height:19pt;
- font-size:95%;
- font-weight:bold;
- margin-bottom:4px;
- margin-left: 0px;
-}
-a {
- color:#0000cc;
- white-space: nowrap;
-}
-.sidebar {
- width: 207px;
- padding:3px 10px 3px 9px;
- -webkit-border-radius:5px 5px;
- margin-bottom:10px;
-}
-</style>
-<script>
-function resizeFrame(newsize) {
- chrome.send("ResizeP13N", [newsize.toString()]);
-}
-</script>
-</head>
-<body>
-<div id="sync" class="sidebar">
- <table id="titletable" width="200" cellpadding="0" cellspacing="0"
- style="display:none">
- <tr>
- <td id="messagetitle" align="left" class="section-title">
- </td>
- <td align="right">
- <a href="#" onclick="resizeFrame(0);">
- <img id="greenclose" src="close.png"/>
- </a>
- </td>
- </tr>
- </table>
- <div id="syncContainer"></div>
-</div>
-<script>
-/* Return a DOM element with tag name |elem| and attributes |attrs|. */
-function DOM(elem, attrs) {
- var elem = document.createElement(elem);
- for (var attr in attrs) {
- elem[attr] = attrs[attr];
- }
- return elem;
-}
-
-function renderSyncMessage(message) {
- var section = document.getElementById('sync');
- var container = document.getElementById('syncContainer');
- var title = document.getElementById('messagetitle');
- var titletable = document.getElementById('titletable');
- container.innerHTML = '';
- title.innerHTML = '';
- titletable.style.display = "none";
- section.style.display = "block";
-
- /* Set the sync section background color. */
- if (message.msgtype == "error") {
- section.style.backgroundColor = "#f8d1ca";
- } else if (message.msgtype == "presynced") {
- section.style.backgroundColor = "#e0f8ca";
- } else {
- section.style.backgroundColor = "#e1ecfe";
- }
-
- if (message.msgtype != "synced") {
- /* Any message except the status normal / synced to
- message requires extra markup for a title, close button,
- and links. */
- var titletxt = document.createTextNode(message.title);
- title.appendChild(titletxt);
- titletable.style.display = "block";
- }
-
- /* The main message of the sync section. */
- var txt = DOM('p');
- txt.style.margin = 0;
- txt.appendChild(document.createTextNode(message.msg));
- container.appendChild(txt);
-
- /* If we should show a link, create the href. */
- if (message.linktext) {
- var link = DOM('a', { href:"#", title: message.linktext});
- link.onclick = function(tt) {
- return function() {
- chrome.send("SyncLinkClicked", [tt]);
- return false;
- }
- } (message.title);
-
- /* Tie it together. */
- link.appendChild(document.createTextNode(message.linktext));
- container.appendChild(link);
- }
-
- /* Tell our container to resize to fit us appropriately. */
- resizeFrame(document.body.scrollHeight);
-}
-
-chrome.send("GetSyncMessage");
-</script>
-</body>
-</html> \ No newline at end of file
diff --git a/chrome/browser/sync/resources/setup_flow.html b/chrome/browser/sync/resources/setup_flow.html
deleted file mode 100644
index 82db8a9..0000000
--- a/chrome/browser/sync/resources/setup_flow.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<HTML id='t'>
-<style type="text/css">
-</style>
-<HEAD>
-<TITLE></TITLE>
-<script>
- function showMergeAndSync() {
- document.getElementById("login").style.display = "none";
- document.getElementById("merge").style.display = "block";
- }
-</script>
-</HEAD>
-<BODY style="margin:0; border:0;">
- <iframe id="login" frameborder="0" width="100%" scrolling="no" height="100%"
- src="cloudy://resources/gaialogin"></iframe>
- <iframe id="merge" frameborder="0" width="100%" scrolling="no" height="100%"
- src="cloudy://resources/mergeandsync" style="display:none"></iframe>
-</BODY>
-</HTML>
diff --git a/chrome/browser/sync/sync_status_ui_helper.cc b/chrome/browser/sync/sync_status_ui_helper.cc
deleted file mode 100644
index 22a1f6c..0000000
--- a/chrome/browser/sync/sync_status_ui_helper.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2009 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#include "chrome/browser/sync/sync_status_ui_helper.h"
-
-#include "base/string_util.h"
-#include "chrome/browser/sync/auth_error_state.h"
-#include "chrome/browser/sync/personalization_strings.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-
-static void GetLabelsForAuthError(AuthErrorState auth_error,
- ProfileSyncService* service, std::wstring* status_label,
- std::wstring* link_label) {
- if (link_label)
- link_label->assign(kSyncReLoginLinkLabel);
- if (auth_error == AUTH_ERROR_INVALID_GAIA_CREDENTIALS) {
- // If the user name is empty then the first login failed, otherwise the
- // credentials are out-of-date.
- if (service->GetAuthenticatedUsername().empty())
- status_label->append(kSyncInvalidCredentialsError);
- else
- status_label->append(kSyncExpiredCredentialsError);
- } else if (auth_error == AUTH_ERROR_CONNECTION_FAILED) {
- // Note that there is little the user can do if the server is not
- // reachable. Since attempting to re-connect is done automatically by
- // the Syncer, we do not show the (re)login link.
- status_label->append(kSyncServerUnavailableMsg);
- if (link_label)
- link_label->clear();
- } else {
- status_label->append(kSyncOtherLoginErrorLabel);
- }
-}
-
-static std::wstring GetSyncedStateStatusLabel(ProfileSyncService* service) {
- std::wstring label;
- std::wstring user_name(UTF16ToWide(service->GetAuthenticatedUsername()));
- if (user_name.empty())
- return label;
-
- label += kSyncAccountLabel;
- label += user_name;
- label += L"\n";
- label += kLastSyncedLabel;
- label += service->GetLastSyncedTimeString();
- return label;
-}
-
-// static
-SyncStatusUIHelper::MessageType SyncStatusUIHelper::GetLabels(
- ProfileSyncService* service, std::wstring* status_label,
- std::wstring* link_label) {
- MessageType result_type(SYNCED);
- bool sync_enabled = service->IsSyncEnabledByUser();
-
- if (sync_enabled) {
- ProfileSyncService::Status status(service->QueryDetailedSyncStatus());
- AuthErrorState auth_error(service->GetAuthErrorState());
- // Either show auth error information with a link to re-login, auth in prog,
- // or note that everything is OK with the last synced time.
- status_label->assign(GetSyncedStateStatusLabel(service));
- if (status.authenticated) {
- // Everything is peachy.
- DCHECK_EQ(auth_error, AUTH_ERROR_NONE);
- } else if (service->UIShouldDepictAuthInProgress()) {
- status_label->append(kSyncAuthenticatingLabel);
- result_type = PRE_SYNCED;
- } else if (auth_error != AUTH_ERROR_NONE) {
- GetLabelsForAuthError(auth_error, service, status_label, link_label);
- result_type = SYNC_ERROR;
- } else {
- NOTREACHED() << "Setup complete, backend !authenticated, AUTH_ERROR_NONE";
- }
- } else {
- // Either show auth error information with a link to re-login, auth in prog,
- // or provide a link to continue with setup.
- result_type = PRE_SYNCED;
- if (service->SetupInProgress()) {
- ProfileSyncService::Status status(service->QueryDetailedSyncStatus());
- AuthErrorState auth_error(service->GetAuthErrorState());
- status_label->assign(UTF8ToWide(kSettingUpText));
- if (service->UIShouldDepictAuthInProgress()) {
- status_label->assign(kSyncAuthenticatingLabel);
- } else if (auth_error != AUTH_ERROR_NONE) {
- status_label->clear();
- GetLabelsForAuthError(auth_error, service, status_label, NULL);
- result_type = SYNC_ERROR;
- } else if (!status.authenticated) {
- status_label->assign(kSyncCredentialsNeededLabel);
- }
- } else {
- status_label->assign(kSyncNotSetupInfo);
- }
- }
- return result_type;
-}
-
-#endif // CHROME_PERSONALIZATION
diff --git a/chrome/browser/sync/sync_status_ui_helper.h b/chrome/browser/sync/sync_status_ui_helper.h
deleted file mode 100644
index 6241ead..0000000
--- a/chrome/browser/sync/sync_status_ui_helper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2009 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.
-
-#ifdef CHROME_PERSONALIZATION
-
-#ifndef CHROME_BROWSER_SYNC_SYNC_STATUS_UI_HELPER_H_
-#define CHROME_BROWSER_SYNC_SYNC_STATUS_UI_HELPER_H_
-
-#include "base/string16.h"
-
-class ProfileSyncService;
-
-// Utility to gather current sync status information from the sync service and
-// constructs messages suitable for showing in UI.
-class SyncStatusUIHelper {
- public:
- enum MessageType {
- PRE_SYNCED, // User has not set up sync.
- SYNCED, // We are synced and authenticated to a gmail account.
- SYNC_ERROR, // A sync error (such as invalid credentials) has occurred.
- };
-
- // Create status and link labels for the current status labels and link text
- // by querying |service|.
- static MessageType GetLabels(ProfileSyncService* service,
- std::wstring* status_label,
- std::wstring* link_label);
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SyncStatusUIHelper);
-};
-
-#endif // CHROME_BROWSER_SYNC_SYNC_STATUS_UI_HELPER_H_
-#endif // CHROME_PERSONALIZATION