This added a bunch of startup time static initializers. Specifically there are many things like:
const std::string Toolbar5Importer::kUrlXmlTag = "url"; These all need to run the std::string constructor on startup, which should be considered a regression... Here is the complete list: _dynamic_initializer_for__Toolbar5Importer__kXmlApiReplyXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kBookmarksXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kBookmarkXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kTitleXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kUrlXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kTimestampXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kLabelsXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kLabelsXmlCloseTag__ _dynamic_initializer_for__Toolbar5Importer__kLabelXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kAttributesXmlTag__ _dynamic_initializer_for__Toolbar5Importer__kRandomNumberToken__ _dynamic_initializer_for__Toolbar5Importer__kAuthorizationToken__ _dynamic_initializer_for__Toolbar5Importer__kAuthorizationTokenPrefix__ _dynamic_initializer_for__Toolbar5Importer__kAuthorizationTokenSuffix__ _dynamic_initializer_for__Toolbar5Importer__kMaxNumToken__ _dynamic_initializer_for__Toolbar5Importer__kMaxTimestampToken__ _dynamic_initializer_for__Toolbar5Importer__kT5AuthorizationTokenUrl__ _dynamic_initializer_for__Toolbar5Importer__kT5FrontEndUrlTemplate__ On Tue, Nov 4, 2008 at 8:54 PM, <[email protected]> wrote: > > Author: [email protected] > Date: Tue Nov 4 11:54:49 2008 > New Revision: 4633 > > Log: > Toolbar Import - Issue 8801, migrated from public tree to svn enlistment. > > Added: > trunk/src/chrome/browser/importer/toolbar_importer.cc > trunk/src/chrome/browser/importer/toolbar_importer.h > Modified: > trunk/src/chrome/app/generated_resources.grd > trunk/src/chrome/browser/browser.vcproj > trunk/src/chrome/browser/importer/importer.cc > trunk/src/chrome/browser/importer/importer.h > trunk/src/chrome/browser/views/importer_view.cc > trunk/src/chrome/browser/views/importer_view.h > > Modified: trunk/src/chrome/app/generated_resources.grd > ============================================================================== > --- trunk/src/chrome/app/generated_resources.grd (original) > +++ trunk/src/chrome/app/generated_resources.grd Tue Nov 4 11:54:49 > 2008 > @@ -1768,6 +1768,9 @@ > <message name="IDS_IMPORT_FROM_FIREFOX" desc="browser combo box: > Mozilla Firefox"> > Mozilla Firefox > </message> > + <message name="IDS_IMPORT_FROM_GOOGLE_TOOLBAR" desc="browser combo > box: Google Toolbar"> > + Google Toolbar > + </message> > <message name="IDS_IMPORT_ITEMS_LABEL" desc="Label before item select > checkboxes"> > Select items to import: > </message> > @@ -1791,6 +1794,10 @@ > Import > </message> > > + <message name="IDS_IMPORTER_GOOGLE_LOGIN_TEXT" desc="The message to be > displayed on dialog"> > + In order to import Toolbar bookmarks into Chrome, you must be logged > into your Google account. Please log in and try to import again. > + </message> > + > <!-- Import progress popup --> > <message name="IDS_IMPORT_PROGRESS_TITLE" desc="Title for the importing > progress dialog"> > Importing > @@ -2032,7 +2039,7 @@ > <message name="IDS_BOOKMARKS_NO_ITEMS" desc="Text shown when the user > has no bookmarks"> > For quick access, place your bookmarks here in the bookmarks bar. > </message> > - > + > <!-- The location for special bookmark groups --> > <message name="IDS_BOOKMARK_GROUP_FROM_IE" desc="The group name of > bookmarks from Internet Explorer"> > Imported From IE > @@ -2040,11 +2047,14 @@ > <message name="IDS_BOOKMARK_GROUP_FROM_FIREFOX" desc="The group name of > bookmarks from Firefox"> > Imported From Firefox > </message> > + <message name="IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR" desc="The group > name of bookmarks from Google Toolbar"> > + Imported From Google Toolbar > + </message> > <message name="IDS_BOOKMARK_GROUP" desc="The group name of bookmarks > imported from a file"> > Imported > </message> > > - <!-- bookmark editor messages--> > + <!-- bookmark editor messages--> > <message name="IDS_BOOMARK_EDITOR_NAME_LABEL" desc="Label shown before > the title/name of the URL."> > Name: > </message> > > Modified: trunk/src/chrome/browser/browser.vcproj > ============================================================================== > --- trunk/src/chrome/browser/browser.vcproj (original) > +++ trunk/src/chrome/browser/browser.vcproj Tue Nov 4 11:54:49 2008 > @@ -722,19 +722,19 @@ > Name="Bookmarks" > > > <File > - > RelativePath=".\bookmarks\bookmark_context_menu.cc" > + RelativePath=".\bookmarks\bookmark_codec.cc" > > > </File> > <File > - > RelativePath=".\bookmarks\bookmark_context_menu.h" > + RelativePath=".\bookmarks\bookmark_codec.h" > > > </File> > <File > - RelativePath=".\bookmarks\bookmark_codec.cc" > + > RelativePath=".\bookmarks\bookmark_context_menu.cc" > > > </File> > <File > - RelativePath=".\bookmarks\bookmark_codec.h" > + > RelativePath=".\bookmarks\bookmark_context_menu.h" > > > </File> > <File > @@ -1577,6 +1577,14 @@ > RelativePath=".\importer\mork_reader.h" > > > </File> > + <File > + RelativePath=".\importer\toolbar_importer.cc" > + > > + </File> > + <File > + RelativePath=".\importer\toolbar_importer.h" > + > > + </File> > </Filter> > <Filter > Name="Drag & Drop" > > Modified: trunk/src/chrome/browser/importer/importer.cc > ============================================================================== > --- trunk/src/chrome/browser/importer/importer.cc (original) > +++ trunk/src/chrome/browser/importer/importer.cc Tue Nov 4 11:54:49 > 2008 > @@ -11,12 +11,16 @@ > #include "base/gfx/png_encoder.h" > #include "base/string_util.h" > #include "chrome/browser/bookmarks/bookmark_model.h" > +#include "chrome/browser/browser.h" > +#include "chrome/browser/browser_list.h" > #include "chrome/browser/browser_process.h" > +#include "chrome/browser/first_run.h" > #include "chrome/browser/importer/firefox2_importer.h" > #include "chrome/browser/importer/firefox3_importer.h" > #include "chrome/browser/importer/firefox_importer_utils.h" > #include "chrome/browser/importer/firefox_profile_lock.h" > #include "chrome/browser/importer/ie_importer.h" > +#include "chrome/browser/importer/toolbar_importer.h" > #include "chrome/browser/template_url_model.h" > #include "chrome/browser/shell_integration.h" > #include "chrome/browser/webdata/web_data_service.h" > @@ -24,6 +28,7 @@ > #include "chrome/common/l10n_util.h" > #include "chrome/common/pref_names.h" > #include "chrome/common/pref_service.h" > +#include "chrome/common/win_util.h" > #include "chrome/views/window.h" > #include "webkit/glue/image_decoder.h" > > @@ -245,7 +250,8 @@ > } > if (t_url->url() && t_url->url()->IsValid()) { > model->Add(t_url); > - if (default_keyword && t_url->url() && > t_url->url()->SupportsReplacement()) > + if (default_keyword && t_url->url() && > + t_url->url()->SupportsReplacement()) > model->SetDefaultSearchProvider(t_url); > } else { > // Don't add invalid TemplateURLs to the model. > @@ -327,6 +333,7 @@ > > ImporterHost::~ImporterHost() { > STLDeleteContainerPointers(source_profiles_.begin(), > source_profiles_.end()); > + if (NULL != importer_) importer_->Release(); > } > > void ImporterHost::Loaded(BookmarkModel* model) { > @@ -386,6 +393,7 @@ > // will be notified. > writer_ = writer; > importer_ = CreateImporterByType(profile_info.browser_type); > + importer_->AddRef(); > importer_->set_first_run(first_run); > task_ = NewRunnableMethod(importer_, &Importer::StartImport, > profile_info, items, writer_.get(), this); > @@ -402,6 +410,27 @@ > } > } > > + if (profile_info.browser_type == GOOGLE_TOOLBAR5) { > + if (!ToolbarImporterUtils::IsGoogleGAIACookieInstalled()) { > + win_util::MessageBox( > + NULL, > + l10n_util::GetString(IDS_IMPORTER_GOOGLE_LOGIN_TEXT).c_str(), > + L"", > + MB_OK | MB_TOPMOST); > + > + GURL url("https://www.google.com/accounts/ServiceLogin"); > + BrowsingInstance* instance = new > BrowsingInstance(writer_->GetProfile()); > + SiteInstance* site = instance->GetSiteInstanceForURL(url); > + Browser* browser = BrowserList::GetLastActive(); > + browser->AddTabWithURL(url, GURL(), PageTransition::TYPED, true, site); > + > + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( > + this, &ImporterHost::OnLockViewEnd, false)); > + > + is_source_readable_ = false; > + } > + } > + > // BookmarkModel should be loaded before adding IE favorites. So we observe > // the BookmarkModel if needed, and start the task after it has been loaded. > if ((items & FAVORITES) && !writer_->BookmarkModelIsLoaded()) { > @@ -469,6 +498,8 @@ > return new Firefox2Importer(); > case FIREFOX3: > return new Firefox3Importer(); > + case GOOGLE_TOOLBAR5: > + return new Toolbar5Importer(); > } > NOTREACHED(); > return NULL; > @@ -489,6 +520,8 @@ > } > > void ImporterHost::DetectSourceProfiles() { > + // The order in which detect is called determines the order > + // in which the options appear in the dropdown combo-box > if (ShellIntegration::IsFirefoxDefaultBrowser()) { > DetectFirefoxProfiles(); > DetectIEProfiles(); > @@ -496,6 +529,8 @@ > DetectIEProfiles(); > DetectFirefoxProfiles(); > } > + > + if (!FirstRun::IsChromeFirstRun()) DetectGoogleToolbarProfiles(); > } > > void ImporterHost::DetectIEProfiles() { > @@ -505,6 +540,8 @@ > ie->browser_type = MS_IE; > ie->source_path.clear(); > ie->app_path.clear(); > + ie->services_supported = HISTORY | FAVORITES | COOKIES | PASSWORDS | > + SEARCH_ENGINES; > source_profiles_.push_back(ie); > } > > @@ -568,7 +605,32 @@ > firefox->browser_type = firefox_type; > firefox->source_path = source_path; > firefox->app_path = GetFirefoxInstallPath(); > + firefox->services_supported = HISTORY | FAVORITES | COOKIES | PASSWORDS | > + SEARCH_ENGINES; > source_profiles_.push_back(firefox); > } > } > > +void ImporterHost::DetectGoogleToolbarProfiles() { > + if (ToolbarImporterUtils::IsToolbarInstalled()) { > + TOOLBAR_VERSION version = ToolbarImporterUtils::GetToolbarVersion(); > + if (DEPRECATED != version) { > + ProfileInfo* google_toolbar = new ProfileInfo(); > + switch (version) { > + // TODO(brg): Support other toolbar version after 1.0. > + case VERSION_5: > + google_toolbar->browser_type = GOOGLE_TOOLBAR5; > + break; > + default: > + NOTREACHED() << "Supported Google Toolbar version not > implemented."; > + break; > + } > + google_toolbar->description = l10n_util::GetString( > + IDS_IMPORT_FROM_GOOGLE_TOOLBAR); > + google_toolbar->source_path.clear(); > + google_toolbar->app_path.clear(); > + google_toolbar->services_supported = FAVORITES; > + source_profiles_.push_back(google_toolbar); > + } > + } > +} > > Modified: trunk/src/chrome/browser/importer/importer.h > ============================================================================== > --- trunk/src/chrome/browser/importer/importer.h (original) > +++ trunk/src/chrome/browser/importer/importer.h Tue Nov 4 11:54:49 > 2008 > @@ -26,7 +26,8 @@ > enum ProfileType { > MS_IE = 0, > FIREFOX2, > - FIREFOX3 > + FIREFOX3, > + GOOGLE_TOOLBAR5 > }; > > // An enumeration of the type of data we want to import. > @@ -38,6 +39,7 @@ > PASSWORDS = 0x0008, > SEARCH_ENGINES = 0x0010, > HOME_PAGE = 0x0020, > + ALL = 0x003f > }; > > typedef struct { > @@ -45,6 +47,7 @@ > ProfileType browser_type; > std::wstring source_path; > std::wstring app_path; > + uint16 services_supported; // bitmap of ImportItem > } ProfileInfo; > > class FirefoxProfileLock; > @@ -103,6 +106,8 @@ > // Shows the bookmarks toolbar. > void ShowBookmarkBar(); > > + Profile* GetProfile() const { return profile_; } > + > private: > Profile* profile_; > > @@ -228,6 +233,7 @@ > // Helper methods for detecting available profiles. > void DetectIEProfiles(); > void DetectFirefoxProfiles(); > + void DetectGoogleToolbarProfiles(); > > // The list of profiles with the default one first. > std::vector<ProfileInfo*> source_profiles_; > > Added: trunk/src/chrome/browser/importer/toolbar_importer.cc > ============================================================================== > --- (empty file) > +++ trunk/src/chrome/browser/importer/toolbar_importer.cc Tue Nov 4 > 11:54:49 2008 > @@ -0,0 +1,578 @@ > +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. > +// Use of this source code is governed by a BSD-style license that can be > +// found in the LICENSE file. > + > +#include "chrome/browser/importer/toolbar_importer.h" > + > +#include <limits> > +#include "base/string_util.h" > +#include "base/rand_util.h" > +#include "base/registry.h" > +#include "chrome/common/l10n_util.h" > +#include "chrome/common/libxml_utils.h" > +#include "net/base/data_url.h" > +#include "net/base/cookie_monster.h" > + > +#include "generated_resources.h" > + > + > +// > +// ToolbarImporterUtils > +// > +const HKEY ToolbarImporterUtils::kToolbarInstallRegistryRoots[] = > + {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE}; > +const TCHAR* ToolbarImporterUtils::kToolbarRootRegistryFolder = > + L"Software\\Google\\Google Toolbar"; > +const TCHAR* ToolbarImporterUtils::kToolbarVersionRegistryFolder = > + L"SOFTWARE\\Google\\Google Toolbar\\Component"; > +const TCHAR* ToolbarImporterUtils::kToolbarVersionRegistryKey = > + L"CurrentVersion"; > + > + > +bool ToolbarImporterUtils::IsToolbarInstalled() { > + for (int index = 0; > + index < arraysize(kToolbarInstallRegistryRoots); > + ++index) { > + RegKey key(kToolbarInstallRegistryRoots[index], > + kToolbarRootRegistryFolder); > + if (key.Valid()) > + return true; > + } > + return false; > +} > + > +bool ToolbarImporterUtils::IsGoogleGAIACookieInstalled() { > + URLRequestContext* context = Profile::GetDefaultRequestContext(); > + net::CookieMonster* store= context->cookie_store(); > + GURL url("http://.google.com/"); > + net::CookieMonster::CookieOptions options = net::CookieMonster::NORMAL; > + std::string cookies = store->GetCookiesWithOptions(url, options); > + std::vector<std::string> cookie_list; > + SplitString(cookies, L';', &cookie_list); > + for (std::vector<std::string>::iterator current = cookie_list.begin(); > + current != cookie_list.end(); > + ++current) { > + size_t position = (*current).find("SID="); > + if (0 == position) > + return true; > + } > + return false; > +} > + > +TOOLBAR_VERSION ToolbarImporterUtils::GetToolbarVersion() { > + TOOLBAR_VERSION toolbar_version = NO_VERSION; > + for (int index = 0; > + (index < arraysize(kToolbarInstallRegistryRoots)) && > + NO_VERSION == toolbar_version; > + ++index) { > + RegKey key(kToolbarInstallRegistryRoots[index], > + kToolbarVersionRegistryFolder); > + if (key.Valid() && key.ValueExists(kToolbarVersionRegistryKey)) { > + TCHAR version_buffer[128]; > + DWORD version_buffer_length = sizeof(version_buffer); > + if (key.ReadValue(kToolbarVersionRegistryKey, > + &version_buffer, > + &version_buffer_length)) { > + int version_value = _wtoi(version_buffer); > + switch (version_value) { > + case 5: { > + toolbar_version = VERSION_5; > + break; > + } > + default: { > + toolbar_version = DEPRECATED; > + break; > + } > + } > + } > + } > + } > + return toolbar_version; > +} > + > +// > +// Toolbar5Importer > +// > + > +const std::string Toolbar5Importer::kXmlApiReplyXmlTag = "xml_api_reply"; > +const std::string Toolbar5Importer::kBookmarksXmlTag = "bookmarks"; > +const std::string Toolbar5Importer::kBookmarkXmlTag = "bookmark"; > +const std::string Toolbar5Importer::kTitleXmlTag = "title"; > +const std::string Toolbar5Importer::kUrlXmlTag = "url"; > +const std::string Toolbar5Importer::kTimestampXmlTag = "timestamp"; > +const std::string Toolbar5Importer::kLabelsXmlTag = "labels"; > +const std::string Toolbar5Importer::kLabelXmlTag = "label"; > +const std::string Toolbar5Importer::kAttributesXmlTag = "attributes"; > +const std::string Toolbar5Importer::kAttributeXmlTag = "attribute"; > +const std::string Toolbar5Importer::kNameXmlTag = "name"; > +const std::string Toolbar5Importer::kValueXmlTag = "favicon"; > +const std::string Toolbar5Importer::kFaviconAttributeXmlName = "favicon_url"; > + > +const std::string Toolbar5Importer::kRandomNumberToken = "{random_number}"; > +const std::string Toolbar5Importer::kAuthorizationToken = "{auth_token}"; > +const std::string Toolbar5Importer::kAuthorizationTokenPrefix = "/*"; > +const std::string Toolbar5Importer::kAuthorizationTokenSuffix = "*/"; > +const std::string Toolbar5Importer::kMaxNumToken = "{max_num}"; > +const std::string Toolbar5Importer::kMaxTimestampToken = "{max_timestamp}"; > + > +const std::string Toolbar5Importer::kT5AuthorizationTokenUrl = > + "http://www.google.com/notebook/token?zx={random_number}"; > +const std::string Toolbar5Importer::kT5FrontEndUrlTemplate = > + "http://www.google.com/notebook/toolbar?cmd=list&tok={auth_token}& " > + "num={max_num}&min={max_timestamp}&all=0&zx={random_number}"; > +const std::string Toolbar5Importer::kT4FrontEndUrlTemplate = > + "http://www.google.com/bookmarks/?output=xml&num={max_num}&" > + "min={max_timestamp}&all=0&zx={random_number}"; > + > +// Importer methods. > +Toolbar5Importer::Toolbar5Importer() : writer_(NULL), > + state_(NOT_USED), > + items_to_import_(NONE), > + token_fetcher_(NULL), > + data_fetcher_(NULL) { > +} > + > +Toolbar5Importer::~Toolbar5Importer() { > + DCHECK(!token_fetcher_); > + DCHECK(!data_fetcher_); > +} > + > +void Toolbar5Importer::StartImport(ProfileInfo profile_info, > + uint16 items, > + ProfileWriter* writer, > + ImporterHost* host) { > + DCHECK(writer); > + DCHECK(host); > + > + importer_host_ = host; > + writer_ = writer; > + items_to_import_ = items; > + state_ = INITIALIZED; > + > + NotifyStarted(); > + ContinueImport(); > +} > + > +void Toolbar5Importer::OnURLFetchComplete( > + const URLFetcher* source, > + const GURL& url, > + const URLRequestStatus& status, > + int response_code, > + const ResponseCookies& cookies, > + const std::string& data) { > + if (200 != response_code) { // HTTP/Ok > + // Display to the user an error dialog and cancel the import > + EndImportBookmarks(false); > + return; > + } > + > + switch (state_) { > + case GET_AUTHORIZATION_TOKEN: > + GetBookmarkDataFromServer(data); > + break; > + case GET_BOOKMARKS: > + GetBookmarsFromServerDataResponse(data); > + break; > + default: > + NOTREACHED() << "Invalid state."; > + EndImportBookmarks(false); > + break; > + } > +} > + > +void Toolbar5Importer::ContinueImport() { > + DCHECK((items_to_import_ == FAVORITES) || (items_to_import_ == NONE)) << > + "The items requested are not supported"; > + > + // The order here is important. Each Begin... will clear the flag > + // of its item before its task finishes and re-enters this method. > + if (NONE == items_to_import_) { > + EndImport(); > + } > + if ((items_to_import_ & FAVORITES) && !cancelled()) { > + items_to_import_ &= ~FAVORITES; > + BeginImportBookmarks(); > + } > + // TODO(brg): Import history, autocomplete, other toolbar information > + // for 2.0 > +} > + > +void Toolbar5Importer::EndImport() { > + // By spec the fetcher's must be destroyed within the same > + // thread they are created. The importer is destroyed in the ui_thread > + // so when we complete in the file_thread we destroy them first. > + if (NULL != token_fetcher_) { > + delete token_fetcher_; > + token_fetcher_ = NULL; > + } > + > + if (NULL != data_fetcher_) { > + delete data_fetcher_; > + data_fetcher_ = NULL; > + } > + > + NotifyEnded(); > +} > + > +void Toolbar5Importer::BeginImportBookmarks() { > + NotifyItemStarted(FAVORITES); > + GetAuthenticationFromServer(); > +} > + > +void Toolbar5Importer::EndImportBookmarks(bool success) { > + NotifyItemEnded(FAVORITES); > + ContinueImport(); > +} > + > + > +// Notebook FE connection managers. > +void Toolbar5Importer::GetAuthenticationFromServer() { > + // Authentication is a token string retreived from the authentication > server > + // To access it we call the url below with a random number replacing the > + // value in the string. > + state_ = GET_AUTHORIZATION_TOKEN; > + > + // Random number construction. > + int random = base::RandInt(0, std::numeric_limits<int>::max()); > + std::string random_string = UintToString(random); > + > + // Retrieve authorization token from the network. > + std::string url_string(kT5AuthorizationTokenUrl); > + url_string.replace(url_string.find(kRandomNumberToken), > + kRandomNumberToken.size(), > + random_string); > + GURL url(url_string); > + > + token_fetcher_ = new URLFetcher(url, URLFetcher::GET, this); > + token_fetcher_->set_request_context(Profile::GetDefaultRequestContext()); > + token_fetcher_->Start(); > +} > + > +void Toolbar5Importer::GetBookmarkDataFromServer(const std::string& > response) { > + state_ = GET_BOOKMARKS; > + > + // Parse and verify the authorization token from the response. > + std::string token; > + if (!ParseAuthenticationTokenResponse(response, &token)) { > + EndImportBookmarks(false); > + return; > + } > + > + // Build the Toolbar FE connection string, and call the server for > + // the xml blob. We must tag the connection string with a random number. > + std::string conn_string = kT5FrontEndUrlTemplate; > + int random = base::RandInt(0, std::numeric_limits<int>::max()); > + std::string random_string = UintToString(random); > + conn_string.replace(conn_string.find(kRandomNumberToken), > + kRandomNumberToken.size(), > + random_string); > + conn_string.replace(conn_string.find(kAuthorizationToken), > + kAuthorizationToken.size(), > + token); > + GURL url(conn_string); > + > + data_fetcher_ = new URLFetcher(url, URLFetcher::GET, this); > + data_fetcher_->set_request_context(Profile::GetDefaultRequestContext()); > + data_fetcher_->Start(); > +} > + > +void Toolbar5Importer::GetBookmarsFromServerDataResponse( > + const std::string& response) { > + bool retval = false; > + XmlReader reader; > + if (reader.Load(response) && !cancelled()) { > + // Construct Bookmarks > + std::vector< ProfileWriter::BookmarkEntry > bookmarks; > + std::vector< history::ImportedFavIconUsage > favicons; > + retval = ParseBookmarksFromReader(&reader, &bookmarks, &favicons); > + if (retval && !cancelled()) { > + AddBookMarksToChrome(bookmarks, favicons); > + } > + } > + EndImportBookmarks(retval); > +} > + > +bool Toolbar5Importer::ParseAuthenticationTokenResponse( > + const std::string& response, > + std::string* token) { > + DCHECK(token); > + > + *token = response; > + size_t position = token->find(kAuthorizationTokenPrefix); > + if (0 != position) > + return false; > + token->replace(position, kAuthorizationTokenPrefix.size(), ""); > + > + position = token->find(kAuthorizationTokenSuffix); > + if (token->size() != (position + kAuthorizationTokenSuffix.size())) > + return false; > + token->replace(position, kAuthorizationTokenSuffix.size(), ""); > + > + return true; > +} > + > +// Parsing > +bool Toolbar5Importer::ParseBookmarksFromReader( > + XmlReader* reader, > + std::vector< ProfileWriter::BookmarkEntry >* bookmarks, > + std::vector< history::ImportedFavIconUsage >* favicons) { > + DCHECK(reader); > + DCHECK(bookmarks); > + DCHECK(favicons); > + > + // The XML blob returned from the server is described in the > + // Toolbar-Notebook/Bookmarks Protocol document located at > + // https://docs.google.com/a/google.com/Doc?docid=cgt3m7dr_24djt62m&hl=en > + // We are searching for the section with structure > + // <bookmarks><bookmark>...</bookmark><bookmark>...</bookmark></bookmarks> > + > + // Locate the |bookmarks| blob. > + if (!reader->SkipToElement()) > + return false; > + > + if (!LocateNextTagByName(reader, kBookmarksXmlTag)) > + return false; > + > + // Parse each |bookmark| blob > + while (LocateNextTagByName(reader, kBookmarkXmlTag)) { > + ProfileWriter::BookmarkEntry bookmark_entry; > + history::ImportedFavIconUsage favicon_entry; > + if (ExtractBookmarkInformation(reader, &bookmark_entry, &favicon_entry)) > { > + bookmarks->push_back(bookmark_entry); > + if (!favicon_entry.favicon_url.is_empty()) > + favicons->push_back(favicon_entry); > + } > + } > + > + return true; > +} > + > +bool Toolbar5Importer::LocateNextTagByName(XmlReader* reader, > + const std::string& tag) { > + // Locate the |tag| blob. > + while (tag != reader->NodeName()) { > + if (!reader->Read()) > + return false; > + } > + return true; > +} > + > +bool Toolbar5Importer::ExtractBookmarkInformation( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* bookmark_entry, > + history::ImportedFavIconUsage* favicon_entry) { > + DCHECK(reader); > + DCHECK(bookmark_entry); > + DCHECK(favicon_entry); > + > + // The following is a typical bookmark entry. > + // The reader should be pointing to the <title> tag at the moment. > + // > + // <bookmark> > + // <title>MyTitle</title> > + // <url>http://www.sohu.com/</url> > + // <timestamp>1153328691085181</timestamp> > + // <id>N123nasdf239</id> > + // <notebook_id>Bxxxxxxx</notebook_id> (for bookmarks, a special id is > used) > + // <section_id>Sxxxxxx</section_id> > + // <has_highlight>0</has_highlight> > + // <labels> > + // <label>China</label> > + // <label>^k</label> (if this special label is present, the note is > deleted) > + // </labels> > + // <attributes> > + // <attribute> > + // <name>favicon_url</name> > + // <value>http://www.sohu.com/favicon.ico</value> > + // </attribute> > + // <attribute> > + // <name>favicon_timestamp</name> > + // <value>1153328653</value> > + // </attribute> > + // <attribute> > + // <name>notebook_name</name> > + // <value>My notebook 0</value> > + // </attribute> > + // <attribute> > + // <name>section_name</name> > + // <value>My section 0</value> > + // </attribute> > + // <attribute> > + // </attributes> > + // </bookmark> > + // > + // We parse the blob in order, title->url->timestamp etc. Any failure > + // causes us to skip this bookmark. Note Favicons are optional so failure > + // to find them is not a failure to parse the blob. > + > + if (!ExtractTitleFromXmlReader(reader, bookmark_entry)) > + return false; > + if (!ExtractUrlFromXmlReader(reader, bookmark_entry)) > + return false; > + if (!ExtractTimeFromXmlReader(reader, bookmark_entry)) > + return false; > + if (!ExtractFolderFromXmlReader(reader, bookmark_entry)) > + return false; > + ExtractFaviconFromXmlReader(reader, bookmark_entry, favicon_entry); > + > + return true; > +} > + > +bool Toolbar5Importer::ExtractNamedValueFromXmlReader(XmlReader* reader, > + const std::string& > name, > + std::string* buffer) { > + DCHECK(reader); > + DCHECK(buffer); > + > + if (name != reader->NodeName()) > + return false; > + if (!reader->ReadElementContent(buffer)) > + return false; > + return true; > +} > + > +bool Toolbar5Importer::ExtractTitleFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry) { > + DCHECK(reader); > + DCHECK(entry); > + > + if (!LocateNextTagByName(reader, kTitleXmlTag)) > + return false; > + std::string buffer; > + if (!ExtractNamedValueFromXmlReader(reader, kTitleXmlTag, &buffer)) { > + return false; > + } > + entry->title = UTF8ToWide(buffer); > + return true; > +} > + > +bool Toolbar5Importer::ExtractUrlFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry) { > + DCHECK(reader); > + DCHECK(entry); > + > + if (!LocateNextTagByName(reader, kUrlXmlTag)) > + return false; > + std::string buffer; > + if (!ExtractNamedValueFromXmlReader(reader, kUrlXmlTag, &buffer)) { > + return false; > + } > + entry->url = GURL(buffer); > + return true; > +} > + > +bool Toolbar5Importer::ExtractTimeFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry) { > + DCHECK(reader); > + DCHECK(entry); > + if (!LocateNextTagByName(reader, kTimestampXmlTag)) > + return false; > + std::string buffer; > + if (!ExtractNamedValueFromXmlReader(reader, kTimestampXmlTag, &buffer)) { > + return false; > + } > + int64 timestamp; > + if (!StringToInt64(buffer, ×tamp)) { > + return false; > + } > + entry->creation_time = base::Time::FromTimeT(timestamp); > + return true; > +} > + > +bool Toolbar5Importer::ExtractFolderFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry) { > + DCHECK(reader); > + DCHECK(entry); > + > + if (!LocateNextTagByName(reader, kLabelsXmlTag)) > + return false; > + if (!LocateNextTagByName(reader, kLabelXmlTag)) > + return false; > + > + std::vector<std::wstring> label_vector; > + std::string label_buffer; > + while (kLabelXmlTag == reader->NodeName() && > + false != reader->ReadElementContent(&label_buffer)) { > + label_vector.push_back(UTF8ToWide(label_buffer)); > + } > + > + // if this is the first run then we place favorites with no labels > + // in the title bar. Else they are placed in the "Google Toolbar" folder. > + if (first_run() && 0 == label_vector.size()) { > + entry->in_toolbar = true; > + } else { > + entry->in_toolbar = false; > + entry->path.push_back(l10n_util::GetString( > + > IDS_BOOKMARK_GROUP_FROM_GOOGLE_TOOLBAR)); > + } > + > + // If there is only one label and it is in the form "xxx:yyy:zzz" this > + // was created from a Firefox folder. We undo the label creation and > + // recreate the correct folder. > + if (1 == label_vector.size()) { > + std::vector< std::wstring > folder_names; > + SplitString(label_vector[0], L':', &folder_names); > + entry->path.insert(entry->path.end(), > + folder_names.begin(), folder_names.end()); > + } else if (0 != label_vector.size()) { > + std::wstring folder_name = label_vector[0]; > + entry->path.push_back(folder_name); > + } > + > + return true; > +} > + > +bool Toolbar5Importer::ExtractFaviconFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* bookmark_entry, > + history::ImportedFavIconUsage* favicon_entry) { > + DCHECK(reader); > + DCHECK(bookmark_entry); > + DCHECK(favicon_entry); > + > + if (!LocateNextTagByName(reader, kAttributesXmlTag)) > + return false; > + if (!LocateNextTagByName(reader, kAttributeXmlTag)) > + return false; > + if (!LocateNextTagByName(reader, kNameXmlTag)) > + return false; > + > + // Attributes are <name>...</name><value>...</value> pairs. The first > + // attribute should be the favicon name tage, and the value is the url. > + std::string buffer; > + if (!ExtractNamedValueFromXmlReader(reader, kNameXmlTag, &buffer)) > + return false; > + if (kFaviconAttributeXmlName != buffer) > + return false; > + if (!ExtractNamedValueFromXmlReader(reader, kValueXmlTag, &buffer)) > + return false; > + > + // Validate the url > + GURL favicon = GURL(buffer); > + if (!favicon.is_valid()) > + return false; > + > + favicon_entry->favicon_url = favicon; > + favicon_entry->urls.insert(bookmark_entry->url); > + > + return true; > +} > + > +// Bookmark creation > +void Toolbar5Importer::AddBookMarksToChrome( > + const std::vector< ProfileWriter::BookmarkEntry >& bookmarks, > + const std::vector< history::ImportedFavIconUsage >& favicons) { > + if (!bookmarks.empty() && !cancelled()) { > + main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, > + &ProfileWriter::AddBookmarkEntry, bookmarks)); > + } > + > + if (!favicons.empty()) { > + main_loop_->PostTask(FROM_HERE, NewRunnableMethod(writer_, > + &ProfileWriter::AddFavicons, favicons)); > + } > +} > > Added: trunk/src/chrome/browser/importer/toolbar_importer.h > ============================================================================== > --- (empty file) > +++ trunk/src/chrome/browser/importer/toolbar_importer.h Tue Nov 4 > 11:54:49 2008 > @@ -0,0 +1,164 @@ > +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. > +// Use of this source code is governed by a BSD-style license that can be > +// found in the LICENSE file. > + > +#ifndef CHROME_BROWSER_IMPORTER_TOOLBAR_IMPROTER_H__ > +#define CHROME_BROWSER_IMPORTER_TOOLBAR_IMPROTER_H__ > + > +#include <string> > +#include <vector> > + > +#include "chrome/browser/importer/importer.h" > +#include "chrome/browser/url_fetcher.h" > + > +class XmlReader; > + > +enum TOOLBAR_VERSION { > + NO_VERSION = -1, > + DEPRECATED, > + VERSION_4, > + VERSION_5 > +}; > + > +class ToolbarImporterUtils { > + public: > + > + static bool IsToolbarInstalled(); > + static bool IsGoogleGAIACookieInstalled(); > + static TOOLBAR_VERSION GetToolbarVersion(); > + > + private: > + static const HKEY kToolbarInstallRegistryRoots[2]; > + static const TCHAR* kToolbarRootRegistryFolder; > + static const TCHAR* kToolbarVersionRegistryFolder; > + static const TCHAR* kToolbarVersionRegistryKey; > + > + ToolbarImporterUtils() {} > + ~ToolbarImporterUtils() {} > + > + DISALLOW_COPY_AND_ASSIGN(ToolbarImporterUtils); > +}; > + > +class Toolbar5Importer : public URLFetcher::Delegate, > + public Importer { > + public: > + Toolbar5Importer(); > + virtual ~Toolbar5Importer(); > + > + // Importer view calls this method to being the process. > + virtual void StartImport(ProfileInfo profile_info, > + uint16 items, > + ProfileWriter* writer, > + ImporterHost* host); > + > + // URLFetcher::Delegate method > + void OnURLFetchComplete(const URLFetcher* source, > + const GURL& url, > + const URLRequestStatus& status, > + int response_code, > + const ResponseCookies& cookies, > + const std::string& data); > + > + private: > + // Internal state > + enum INTERNAL_STATE { > + NOT_USED = -1, > + INITIALIZED, > + GET_AUTHORIZATION_TOKEN, > + GET_BOOKMARKS, > + DONE > + }; > + > + // URLs for connecting to the toolbar front end > + static const std::string kT5AuthorizationTokenUrl; > + static const std::string kT5FrontEndUrlTemplate; > + static const std::string kT4FrontEndUrlTemplate; > + > + // Token replacement tags > + static const std::string kRandomNumberToken; > + static const std::string kAuthorizationToken; > + static const std::string kAuthorizationTokenPrefix; > + static const std::string kAuthorizationTokenSuffix; > + static const std::string kMaxNumToken; > + static const std::string kMaxTimestampToken; > + > + // XML tag names > + static const std::string kXmlApiReplyXmlTag; > + static const std::string kBookmarksXmlTag; > + static const std::string kBookmarkXmlTag; > + static const std::string kTitleXmlTag; > + static const std::string kUrlXmlTag; > + static const std::string kTimestampXmlTag; > + static const std::string kLabelsXmlTag; > + static const std::string kLabelXmlTag; > + static const std::string kAttributesXmlTag; > + static const std::string kAttributeXmlTag; > + static const std::string kNameXmlTag; > + static const std::string kValueXmlTag; > + static const std::string kFaviconAttributeXmlName; > + > + // Flow control > + void ContinueImport(); > + void EndImport(); > + void BeginImportBookmarks(); > + void EndImportBookmarks(bool success); > + > + // Network I/O > + void GetAuthenticationFromServer(); > + void GetBookmarkDataFromServer(const std::string& response); > + void GetBookmarsFromServerDataResponse(const std::string& response); > + > + // XML Parsing > + bool ParseAuthenticationTokenResponse(const std::string& response, > + std::string* token); > + void ConstructFEConnectionString(const std::string& token, > + std::string* conn_string); > + > + bool ParseBookmarksFromReader( > + XmlReader* reader, > + std::vector< ProfileWriter::BookmarkEntry >* bookmarks, > + std::vector< history::ImportedFavIconUsage >* favicons); > + > + bool LocateNextTagByName(XmlReader* reader, const std::string& tag); > + > + bool ExtractBookmarkInformation(XmlReader* reader, > + ProfileWriter::BookmarkEntry* > bookmark_entry, > + history::ImportedFavIconUsage* > favicon_entry); > + bool ExtractNamedValueFromXmlReader(XmlReader* reader, > + const std::string& name, > + std::string* buffer); > + bool ExtractTitleFromXmlReader(XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry); > + bool ExtractUrlFromXmlReader(XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry); > + bool ExtractTimeFromXmlReader(XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry); > + bool ExtractFolderFromXmlReader(XmlReader* reader, > + ProfileWriter::BookmarkEntry* entry); > + bool ExtractFaviconFromXmlReader( > + XmlReader* reader, > + ProfileWriter::BookmarkEntry* bookmark_entry, > + history::ImportedFavIconUsage* favicon_entry); > + > + // Bookmark creation > + void AddBookMarksToChrome( > + const std::vector< ProfileWriter::BookmarkEntry >& bookmarks, > + const std::vector< history::ImportedFavIconUsage >& favicons); > + > + // Hosts the writer used in this importer. > + ProfileWriter* writer_; > + > + // Internal state > + INTERNAL_STATE state_; > + > + // Bitmask of Importer::ImportItem > + uint16 items_to_import_; > + > + // The fetchers need to be available to cancel the network call on user > cancel > + URLFetcher * token_fetcher_; > + URLFetcher * data_fetcher_; > + > + DISALLOW_COPY_AND_ASSIGN(Toolbar5Importer); > +}; > + > +#endif // CHROME_BROWSER_IMPORTER_TOOLBAR_IMPROTER_H__ > > Modified: trunk/src/chrome/browser/views/importer_view.cc > ============================================================================== > --- trunk/src/chrome/browser/views/importer_view.cc (original) > +++ trunk/src/chrome/browser/views/importer_view.cc Tue Nov 4 11:54:49 > 2008 > @@ -41,6 +41,7 @@ > new views::Label(l10n_util::GetString(IDS_IMPORT_FROM_LABEL)); > > profile_combobox_ = new views::ComboBox(this); > + profile_combobox_->SetListener(this); > > import_items_label_ = > new views::Label(l10n_util::GetString(IDS_IMPORT_ITEMS_LABEL)); > @@ -120,16 +121,7 @@ > return false; > } > > - uint16 items = NONE; > - if (history_checkbox_->IsEnabled() && history_checkbox_->IsSelected()) > - items |= HISTORY; > - if (favorites_checkbox_->IsEnabled() && favorites_checkbox_->IsSelected()) > - items |= FAVORITES; > - if (passwords_checkbox_->IsEnabled() && passwords_checkbox_->IsSelected()) > - items |= PASSWORDS; > - if (search_engines_checkbox_->IsEnabled() && > - search_engines_checkbox_->IsSelected()) > - items |= SEARCH_ENGINES; > + uint16 items = GetCheckedItems(); > > Browser* browser = BrowserList::GetLastActive(); > int selected_index = profile_combobox_->GetSelectedItem(); > @@ -149,7 +141,10 @@ > int ImporterView::GetItemCount(views::ComboBox* source) { > DCHECK(source == profile_combobox_); > DCHECK(importer_host_.get()); > - return importer_host_->GetAvailableProfileCount(); > + int item_count = importer_host_->GetAvailableProfileCount(); > + if (checkbox_items_.size() < static_cast<size_t>(item_count)) > + checkbox_items_.resize(item_count, ALL); > + return item_count; > } > > std::wstring ImporterView::GetItemAt(views::ComboBox* source, int index) { > @@ -158,6 +153,29 @@ > return importer_host_->GetSourceProfileNameAt(index); > } > > +void ImporterView::ItemChanged(views::ComboBox* combo_box, > + int prev_index, int new_index) { > + DCHECK(combo_box); > + DCHECK(checkbox_items_.size() >= > + static_cast<size_t>(importer_host_->GetAvailableProfileCount())); > + > + if (prev_index == new_index) > + return; > + > + // Save the current state > + uint16 prev_items = GetCheckedItems(); > + checkbox_items_[prev_index] = prev_items; > + > + // Enable/Disable the checkboxes for this Item > + uint16 new_enabled_items = importer_host_->GetSourceProfileInfoAt( > + new_index).services_supported; > + SetCheckedItemsState(new_enabled_items); > + > + // Set the checked items for this Item > + uint16 new_items = checkbox_items_[new_index]; > + SetCheckedItems(new_items); > +} > + > void ImporterView::ImportCanceled() { > ImportComplete(); > } > @@ -174,3 +192,77 @@ > return checkbox; > } > > +uint16 ImporterView::GetCheckedItems() { > + uint16 items = NONE; > + if (history_checkbox_->IsEnabled() && history_checkbox_->IsSelected()) > + items |= HISTORY; > + if (favorites_checkbox_->IsEnabled() && favorites_checkbox_->IsSelected()) > + items |= FAVORITES; > + if (passwords_checkbox_->IsEnabled() && passwords_checkbox_->IsSelected()) > + items |= PASSWORDS; > + if (search_engines_checkbox_->IsEnabled() && > + search_engines_checkbox_->IsSelected()) > + items |= SEARCH_ENGINES; > + return items; > +} > + > +void ImporterView::SetCheckedItemsState(uint16 items) { > + if (items & HISTORY) { > + history_checkbox_->SetEnabled(true); > + } else { > + history_checkbox_->SetEnabled(false); > + history_checkbox_->SetIsSelected(false); > + } > + if (items & FAVORITES) { > + favorites_checkbox_->SetEnabled(true); > + } else { > + favorites_checkbox_->SetEnabled(false); > + favorites_checkbox_->SetIsSelected(false); > + } > + if (items & PASSWORDS) { > + passwords_checkbox_->SetEnabled(true); > + } else { > + passwords_checkbox_->SetEnabled(false); > + passwords_checkbox_->SetIsSelected(false); > + } > + if (items & SEARCH_ENGINES) { > + search_engines_checkbox_->SetEnabled(true); > + } else { > + search_engines_checkbox_->SetEnabled(false); > + search_engines_checkbox_->SetIsSelected(false); > + } > +} > + > +void ImporterView::SetCheckedItems(uint16 items) { > + if (history_checkbox_->IsEnabled()) { > + if (items & HISTORY) { > + history_checkbox_->SetIsSelected(true); > + } else { > + history_checkbox_->SetIsSelected(false); > + } > + } > + > + if (favorites_checkbox_->IsEnabled()) { > + if (items & FAVORITES) { > + favorites_checkbox_->SetIsSelected(true); > + } else { > + favorites_checkbox_->SetIsSelected(false); > + } > + } > + > + if (passwords_checkbox_->IsEnabled()) { > + if (items & PASSWORDS) { > + passwords_checkbox_->SetIsSelected(true); > + } else { > + passwords_checkbox_->SetIsSelected(false); > + } > + } > + > + if (search_engines_checkbox_->IsEnabled()) { > + if (items & SEARCH_ENGINES) { > + search_engines_checkbox_->SetIsSelected(true); > + } else { > + search_engines_checkbox_->SetIsSelected(false); > + } > + } > +} > > Modified: trunk/src/chrome/browser/views/importer_view.h > ============================================================================== > --- trunk/src/chrome/browser/views/importer_view.h (original) > +++ trunk/src/chrome/browser/views/importer_view.h Tue Nov 4 11:54:49 > 2008 > @@ -26,6 +26,7 @@ > class ImporterView : public views::View, > public views::DialogDelegate, > public views::ComboBox::Model, > + public views::ComboBox::Listener, > public ImportObserver { > public: > explicit ImporterView(Profile* profile); > @@ -46,6 +47,11 @@ > virtual int GetItemCount(views::ComboBox* source); > virtual std::wstring GetItemAt(views::ComboBox* source, int index); > > + // Overridden from ChromeViews::ComboBox::Listener > + virtual void ItemChanged(views::ComboBox* combo_box, > + int prev_index, > + int new_index); > + > // Overridden from ImportObserver: > virtual void ImportCanceled(); > virtual void ImportComplete(); > @@ -57,6 +63,15 @@ > // Creates and initializes a new check-box. > views::CheckBox* InitCheckbox(const std::wstring& text, bool checked); > > + // Create a bitmap from the checkboxes of the view. > + uint16 GetCheckedItems(); > + > + // Enables/Disables all the checked items for the given state > + void SetCheckedItemsState(uint16 items); > + > + // Sets all checked items in the given state > + void SetCheckedItems(uint16 items); > + > views::Label* import_from_label_; > views::ComboBox* profile_combobox_; > views::Label* import_items_label_; > @@ -67,6 +82,10 @@ > > scoped_refptr<ImporterHost> importer_host_; > > + // Stores the state of the checked items associated with the position of > the > + // selected item in the combo-box. > + std::vector<uint16> checkbox_items_; > + > Profile* profile_; > > DISALLOW_EVIL_CONSTRUCTORS(ImporterView); > > > > --~--~---------~--~----~------------~-------~--~----~ Chromium Developers mailing list: [email protected] View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~----------~----~----~----~------~----~------~--~---
