1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/toolbar_importer.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/rand_util.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_number_conversions.h"
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/first_run/first_run.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/importer_bridge.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/importer_data_types.h"
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/libxml_utils.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Toolbar5Importer
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kXmlApiReplyXmlTag[] = "xml_api_reply";
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kBookmarksXmlTag[] = "bookmarks";
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kBookmarkXmlTag[] = "bookmark";
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kTitleXmlTag[] = "title";
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kUrlXmlTag[] = "url";
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kTimestampXmlTag[] = "timestamp";
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kLabelsXmlTag[] = "labels";
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kLabelsXmlCloseTag[] = "/labels";
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kLabelXmlTag[] = "label";
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kAttributesXmlTag[] = "attributes";
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kRandomNumberToken[] = "{random_number}";
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kAuthorizationToken[] = "{auth_token}";
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kAuthorizationTokenPrefix[] = "/*";
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kAuthorizationTokenSuffix[] = "*/";
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kMaxNumToken[] = "{max_num}";
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kMaxTimestampToken[] = "{max_timestamp}";
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kT5AuthorizationTokenUrl[] =
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "http://www.google.com/notebook/token?zx={random_number}";
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Toolbar5Importer::kT5FrontEndUrlTemplate[] =
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "http://www.google.com/notebook/toolbar?cmd=list&tok={auth_token}&"
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "num={max_num}&min={max_timestamp}&all=0&zx={random_number}";
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochToolbar5Importer::Toolbar5Importer()
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : state_(NOT_USED),
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      items_to_import_(importer::NONE),
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      token_fetcher_(NULL),
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_fetcher_(NULL) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The destructor insures that the fetchers are currently not being used, as
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// their thread-safe implementation requires that they are cancelled from the
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// thread in which they were constructed.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochToolbar5Importer::~Toolbar5Importer() {
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!token_fetcher_);
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!data_fetcher_);
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Toolbar5Importer::StartImport(
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const importer::SourceProfile& source_profile,
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    uint16 items,
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ImporterBridge* bridge) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bridge);
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_ = bridge;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  items_to_import_ = items;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_ = INITIALIZED;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_->NotifyStarted();
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContinueImport();
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// The public cancel method serves two functions, as a callback from the UI as
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// well as an internal callback in case of cancel.  An internal callback is
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// required since the URLFetcher must be destroyed from the thread it was
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// created.
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::Cancel() {
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // In the case when the thread is not importing messages we are to cancel as
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // soon as possible.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Importer::Cancel();
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we are conducting network operations, post a message to the importer
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // thread for synchronization.
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI, FROM_HERE,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this, &Toolbar5Importer::Cancel));
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::OnURLFetchComplete(
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const URLFetcher* source,
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url,
983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const net::URLRequestStatus& status,
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int response_code,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ResponseCookies& cookies,
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& data) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelled()) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (200 != response_code) {  // HTTP/Ok
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Cancelling here will update the UI and bypass the rest of bookmark
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // import.
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImportBookmarks();
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (state_) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GET_AUTHORIZATION_TOKEN:
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetBookmarkDataFromServer(data);
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GET_BOOKMARKS:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetBookmarksFromServerDataResponse(data);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Invalid state.";
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EndImportBookmarks();
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::ContinueImport() {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK((items_to_import_ == importer::FAVORITES) ||
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         (items_to_import_ == importer::NONE)) <<
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "The items requested are not supported";
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The order here is important.  Each Begin... will clear the flag
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of its item before its task finishes and re-enters this method.
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (importer::NONE == items_to_import_) {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((items_to_import_ & importer::FAVORITES) && !cancelled()) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    items_to_import_ &= ~importer::FAVORITES;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BeginImportBookmarks();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(brg): Import history, autocomplete, other toolbar information
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in a future release.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This code should not be reached, but gracefully handles the possibility
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that StartImport was called with unsupported items_to_import.
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cancelled())
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::EndImport() {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (state_ != DONE) {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    state_ = DONE;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // By spec the fetchers must be destroyed within the same
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // thread they are created.  The importer is destroyed in the ui_thread
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // so when we complete in the file_thread we destroy them first.
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (NULL != token_fetcher_) {
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete token_fetcher_;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      token_fetcher_ = NULL;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (NULL != data_fetcher_) {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete data_fetcher_;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_fetcher_ = NULL;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (bridge_)
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      bridge_->NotifyEnded();
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::BeginImportBookmarks() {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_->NotifyItemStarted(importer::FAVORITES);
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetAuthenticationFromServer();
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::EndImportBookmarks() {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bridge_->NotifyItemEnded(importer::FAVORITES);
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContinueImport();
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Notebook front-end connection manager implementation follows.
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::GetAuthenticationFromServer() {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelled()) {
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Authentication is a token string retrieved from the authentication server
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To access it we call the url below with a random number replacing the
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // value in the string.
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_ = GET_AUTHORIZATION_TOKEN;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Random number construction.
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int random = base::RandInt(0, std::numeric_limits<int>::max());
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string random_string = base::UintToString(random);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Retrieve authorization token from the network.
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url_string(kT5AuthorizationTokenUrl);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_string.replace(url_string.find(kRandomNumberToken),
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     arraysize(kRandomNumberToken) - 1,
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     random_string);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url(url_string);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  token_fetcher_ = new  URLFetcher(url, URLFetcher::GET, this);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  token_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  token_fetcher_->Start();
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::GetBookmarkDataFromServer(const std::string& response) {
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelled()) {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_ = GET_BOOKMARKS;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Parse and verify the authorization token from the response.
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string token;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ParseAuthenticationTokenResponse(response, &token)) {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImportBookmarks();
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build the Toolbar FE connection string, and call the server for
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the xml blob.  We must tag the connection string with a random number.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string conn_string = kT5FrontEndUrlTemplate;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int random = base::RandInt(0, std::numeric_limits<int>::max());
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string random_string = base::UintToString(random);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  conn_string.replace(conn_string.find(kRandomNumberToken),
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      arraysize(kRandomNumberToken) - 1,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      random_string);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  conn_string.replace(conn_string.find(kAuthorizationToken),
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      arraysize(kAuthorizationToken) - 1,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      token);
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url(conn_string);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data_fetcher_ = new URLFetcher(url, URLFetcher::GET, this);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data_fetcher_->Start();
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Toolbar5Importer::GetBookmarksFromServerDataResponse(
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& response) {
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelled()) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EndImport();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  state_ = PARSE_BOOKMARKS;
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  XmlReader reader;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (reader.Load(response) && !cancelled()) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct Bookmarks
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<ProfileWriter::BookmarkEntry> bookmarks;
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ParseBookmarksFromReader(&reader, &bookmarks,
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR)))
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddBookmarksToChrome(bookmarks);
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EndImportBookmarks();
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ParseAuthenticationTokenResponse(
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& response,
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string* token) {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(token);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *token = response;
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t position = token->find(kAuthorizationTokenPrefix);
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (0 != position)
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  token->replace(position, arraysize(kAuthorizationTokenPrefix) - 1, "");
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  position = token->find(kAuthorizationTokenSuffix);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (token->size() != (position + (arraysize(kAuthorizationTokenSuffix) - 1)))
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  token->replace(position, arraysize(kAuthorizationTokenSuffix) - 1, "");
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Parsing
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ParseBookmarksFromReader(
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<ProfileWriter::BookmarkEntry>* bookmarks,
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const string16& bookmark_group_string) {
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bookmarks);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The XML blob returned from the server is described in the
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Toolbar-Notebook/Bookmarks Protocol document located at
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // https://docs.google.com/a/google.com/Doc?docid=cgt3m7dr_24djt62m&hl=en
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We are searching for the section with structure
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <bookmarks><bookmark>...</bookmark><bookmark>...</bookmark></bookmarks>
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Locate the |bookmarks| blob.
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!reader->SkipToElement())
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!LocateNextTagByName(reader, kBookmarksXmlTag))
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Parse each |bookmark| blob
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (LocateNextTagWithStopByName(reader, kBookmarkXmlTag,
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     kBookmarksXmlTag)) {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileWriter::BookmarkEntry bookmark_entry;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<BookmarkFolderType> folders;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ExtractBookmarkInformation(reader, &bookmark_entry, &folders,
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   bookmark_group_string)) {
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // For each folder we create a new bookmark entry.  Duplicates will
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // be detected when we attempt to create the bookmark in the profile.
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (std::vector<BookmarkFolderType>::iterator folder = folders.begin();
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          folder != folders.end();
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ++folder) {
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bookmark_entry.path = *folder;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bookmarks->push_back(bookmark_entry);
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (0 == bookmarks->size())
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::LocateNextOpenTag(XmlReader* reader) {
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (!reader->SkipToElement()) {
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!reader->Read())
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::LocateNextTagByName(XmlReader* reader,
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const std::string& tag) {
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Locate the |tag| blob.
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (tag != reader->NodeName()) {
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!reader->Read() || !LocateNextOpenTag(reader))
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::LocateNextTagWithStopByName(XmlReader* reader,
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                   const std::string& tag,
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                   const std::string& stop) {
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(tag, stop);
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Locate the |tag| blob.
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (tag != reader->NodeName()) {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Move to the next open tag.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!reader->Read() || !LocateNextOpenTag(reader))
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If we encounter the stop word return false.
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (stop == reader->NodeName())
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractBookmarkInformation(
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileWriter::BookmarkEntry* bookmark_entry,
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<BookmarkFolderType>* bookmark_folders,
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const string16& bookmark_group_string) {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bookmark_entry);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bookmark_folders);
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The following is a typical bookmark entry.
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The reader should be pointing to the <title> tag at the moment.
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <bookmark>
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <title>MyTitle</title>
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <url>http://www.sohu.com/</url>
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <timestamp>1153328691085181</timestamp>
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <id>N123nasdf239</id>
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <notebook_id>Bxxxxxxx</notebook_id> (for bookmarks, a special id is used)
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <section_id>Sxxxxxx</section_id>
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <has_highlight>0</has_highlight>
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <labels>
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <label>China</label>
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <label>^k</label> (if this special label is present, the note is deleted)
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </labels>
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <attributes>
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <attribute>
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <name>favicon_url</name>
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <value>http://www.sohu.com/favicon.ico</value>
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </attribute>
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <attribute>
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <name>favicon_timestamp</name>
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <value>1153328653</value>
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </attribute>
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <attribute>
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <name>notebook_name</name>
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <value>My notebook 0</value>
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </attribute>
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <attribute>
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <name>section_name</name>
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // <value>My section 0</value>
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </attribute>
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </attributes>
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // </bookmark>
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We parse the blob in order, title->url->timestamp etc.  Any failure
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // causes us to skip this bookmark.
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractTitleFromXmlReader(reader, bookmark_entry))
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractUrlFromXmlReader(reader, bookmark_entry))
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractTimeFromXmlReader(reader, bookmark_entry))
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractFoldersFromXmlReader(reader, bookmark_folders,
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   bookmark_group_string))
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractNamedValueFromXmlReader(XmlReader* reader,
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                      const std::string& name,
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                      std::string* buffer) {
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(buffer);
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (name != reader->NodeName())
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!reader->ReadElementContent(buffer))
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractTitleFromXmlReader(
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileWriter::BookmarkEntry* entry) {
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!LocateNextTagWithStopByName(reader, kTitleXmlTag, kUrlXmlTag))
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string buffer;
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractNamedValueFromXmlReader(reader, kTitleXmlTag, &buffer)) {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  entry->title = UTF8ToUTF16(buffer);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractUrlFromXmlReader(
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileWriter::BookmarkEntry* entry) {
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!LocateNextTagWithStopByName(reader, kUrlXmlTag, kTimestampXmlTag))
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string buffer;
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractNamedValueFromXmlReader(reader, kUrlXmlTag, &buffer)) {
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->url = GURL(buffer);
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractTimeFromXmlReader(
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProfileWriter::BookmarkEntry* entry) {
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!LocateNextTagWithStopByName(reader, kTimestampXmlTag, kLabelsXmlTag))
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string buffer;
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ExtractNamedValueFromXmlReader(reader, kTimestampXmlTag, &buffer)) {
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 timestamp;
4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!base::StringToInt64(buffer, &timestamp)) {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->creation_time = base::Time::FromTimeT(timestamp);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Toolbar5Importer::ExtractFoldersFromXmlReader(
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    XmlReader* reader,
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<BookmarkFolderType>* bookmark_folders,
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const string16& bookmark_group_string) {
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(reader);
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bookmark_folders);
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read in the labels for this bookmark from the xml.  There may be many
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // labels for any one bookmark.
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!LocateNextTagWithStopByName(reader, kLabelsXmlTag, kAttributesXmlTag))
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It is within scope to have an empty labels section, so we do not
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // return false if the labels are empty.
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!reader->Read() || !LocateNextOpenTag(reader))
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<string16> label_vector;
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (kLabelXmlTag == reader->NodeName()) {
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string label_buffer;
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!reader->ReadElementContent(&label_buffer)) {
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      label_buffer = "";
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    label_vector.push_back(UTF8ToUTF16(label_buffer));
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LocateNextOpenTag(reader);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (0 == label_vector.size()) {
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!FirstRun::IsChromeFirstRun()) {
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_folders->resize(1);
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (*bookmark_folders)[0].push_back(bookmark_group_string);
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We will be making one bookmark folder for each label.
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bookmark_folders->resize(label_vector.size());
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t index = 0; index < label_vector.size(); ++index) {
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If this is the first run then we place favorites with no labels
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // in the title bar.  Else they are placed in the "Google Toolbar" folder.
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!FirstRun::IsChromeFirstRun() || !label_vector[index].empty()) {
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (*bookmark_folders)[index].push_back(bookmark_group_string);
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the label and is in the form "xxx:yyy:zzz" this was created from an
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // IE or Firefox folder.  We undo the label creation and recreate the
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // correct folder.
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<string16> folder_names;
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::SplitString(label_vector[index], ':', &folder_names);
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*bookmark_folders)[index].insert((*bookmark_folders)[index].end(),
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        folder_names.begin(), folder_names.end());
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid  Toolbar5Importer::AddBookmarksToChrome(
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<ProfileWriter::BookmarkEntry>& bookmarks) {
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmarks.empty() && !cancelled()) {
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const string16& first_folder_name =
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bridge_->GetLocalizedString(IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR);
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int options = ProfileWriter::ADD_IF_UNIQUE |
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (import_to_bookmark_bar() ? ProfileWriter::IMPORT_TO_BOOKMARK_BAR : 0);
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bridge_->AddBookmarkEntries(bookmarks, first_folder_name, options);
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
561