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, ×tamp)) { 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