1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/importer/importer_list.h" 6 7 #include "base/bind.h" 8 #include "chrome/browser/importer/importer_list_observer.h" 9 #include "chrome/browser/shell_integration.h" 10 #include "chrome/common/importer/firefox_importer_utils.h" 11 #include "chrome/common/importer/importer_bridge.h" 12 #include "chrome/common/importer/importer_data_types.h" 13 #include "grit/generated_resources.h" 14 #include "ui/base/l10n/l10n_util.h" 15 16 #if defined(OS_MACOSX) 17 #include <CoreFoundation/CoreFoundation.h> 18 19 #include "base/mac/foundation_util.h" 20 #include "chrome/common/importer/safari_importer_utils.h" 21 #endif 22 23 using content::BrowserThread; 24 25 namespace { 26 27 #if defined(OS_WIN) 28 void DetectIEProfiles(std::vector<importer::SourceProfile*>* profiles) { 29 // IE always exists and doesn't have multiple profiles. 30 importer::SourceProfile* ie = new importer::SourceProfile; 31 ie->importer_name = l10n_util::GetStringUTF16(IDS_IMPORT_FROM_IE); 32 ie->importer_type = importer::TYPE_IE; 33 ie->source_path.clear(); 34 ie->app_path.clear(); 35 ie->services_supported = importer::HISTORY | importer::FAVORITES | 36 importer::COOKIES | importer::PASSWORDS | importer::SEARCH_ENGINES; 37 profiles->push_back(ie); 38 } 39 #endif // defined(OS_WIN) 40 41 #if defined(OS_MACOSX) 42 void DetectSafariProfiles(std::vector<importer::SourceProfile*>* profiles) { 43 uint16 items = importer::NONE; 44 if (!SafariImporterCanImport(base::mac::GetUserLibraryPath(), &items)) 45 return; 46 47 importer::SourceProfile* safari = new importer::SourceProfile; 48 safari->importer_name = l10n_util::GetStringUTF16(IDS_IMPORT_FROM_SAFARI); 49 safari->importer_type = importer::TYPE_SAFARI; 50 safari->source_path.clear(); 51 safari->app_path.clear(); 52 safari->services_supported = items; 53 profiles->push_back(safari); 54 } 55 #endif // defined(OS_MACOSX) 56 57 // |locale|: The application locale used for lookups in Firefox's 58 // locale-specific search engines feature (see firefox_importer.cc for 59 // details). 60 void DetectFirefoxProfiles(const std::string locale, 61 std::vector<importer::SourceProfile*>* profiles) { 62 base::FilePath profile_path = GetFirefoxProfilePath(); 63 if (profile_path.empty()) 64 return; 65 66 // Detects which version of Firefox is installed. 67 importer::ImporterType firefox_type; 68 base::FilePath app_path; 69 int version = 0; 70 #if defined(OS_WIN) 71 version = GetCurrentFirefoxMajorVersionFromRegistry(); 72 #endif 73 if (version < 2) 74 GetFirefoxVersionAndPathFromProfile(profile_path, &version, &app_path); 75 76 if (version >= 3) { 77 firefox_type = importer::TYPE_FIREFOX; 78 } else { 79 // Ignores old versions of firefox. 80 return; 81 } 82 83 importer::SourceProfile* firefox = new importer::SourceProfile; 84 firefox->importer_name = GetFirefoxImporterName(app_path); 85 firefox->importer_type = firefox_type; 86 firefox->source_path = profile_path; 87 #if defined(OS_WIN) 88 firefox->app_path = GetFirefoxInstallPathFromRegistry(); 89 #endif 90 if (firefox->app_path.empty()) 91 firefox->app_path = app_path; 92 firefox->services_supported = importer::HISTORY | importer::FAVORITES | 93 importer::PASSWORDS | importer::SEARCH_ENGINES; 94 firefox->locale = locale; 95 profiles->push_back(firefox); 96 } 97 98 } // namespace 99 100 ImporterList::ImporterList() 101 : source_thread_id_(BrowserThread::UI), 102 observer_(NULL), 103 is_observed_(false), 104 source_profiles_loaded_(false) { 105 } 106 107 void ImporterList::DetectSourceProfiles( 108 const std::string& locale, 109 importer::ImporterListObserver* observer) { 110 DCHECK(observer); 111 observer_ = observer; 112 is_observed_ = true; 113 114 bool res = BrowserThread::GetCurrentThreadIdentifier(&source_thread_id_); 115 DCHECK(res); 116 117 BrowserThread::PostTask( 118 BrowserThread::FILE, 119 FROM_HERE, 120 base::Bind(&ImporterList::DetectSourceProfilesWorker, this, locale)); 121 } 122 123 void ImporterList::DetectSourceProfilesHack(const std::string& locale) { 124 DetectSourceProfilesWorker(locale); 125 } 126 127 const importer::SourceProfile& ImporterList::GetSourceProfileAt( 128 size_t index) const { 129 DCHECK(source_profiles_loaded_); 130 DCHECK_LT(index, count()); 131 return *source_profiles_[index]; 132 } 133 134 const importer::SourceProfile& ImporterList::GetSourceProfileForImporterType( 135 int importer_type) const { 136 DCHECK(source_profiles_loaded_); 137 138 for (size_t i = 0; i < count(); ++i) { 139 if (source_profiles_[i]->importer_type == importer_type) 140 return *source_profiles_[i]; 141 } 142 NOTREACHED(); 143 return *(new importer::SourceProfile); 144 } 145 146 ImporterList::~ImporterList() { 147 } 148 149 void ImporterList::DetectSourceProfilesWorker(const std::string& locale) { 150 // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is 151 // removed. 152 if (is_observed_) 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 154 155 std::vector<importer::SourceProfile*> profiles; 156 157 // The first run import will automatically take settings from the first 158 // profile detected, which should be the user's current default. 159 #if defined(OS_WIN) 160 if (ShellIntegration::IsFirefoxDefaultBrowser()) { 161 DetectFirefoxProfiles(locale, &profiles); 162 DetectIEProfiles(&profiles); 163 } else { 164 DetectIEProfiles(&profiles); 165 DetectFirefoxProfiles(locale, &profiles); 166 } 167 #elif defined(OS_MACOSX) 168 if (ShellIntegration::IsFirefoxDefaultBrowser()) { 169 DetectFirefoxProfiles(locale, &profiles); 170 DetectSafariProfiles(&profiles); 171 } else { 172 DetectSafariProfiles(&profiles); 173 DetectFirefoxProfiles(locale, &profiles); 174 } 175 #else 176 DetectFirefoxProfiles(locale, &profiles); 177 #endif 178 importer::SourceProfile* bookmarks_file = new importer::SourceProfile; 179 bookmarks_file->importer_name = 180 l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE); 181 bookmarks_file->importer_type = importer::TYPE_BOOKMARKS_FILE; 182 bookmarks_file->services_supported = importer::FAVORITES; 183 profiles.push_back(bookmarks_file); 184 185 // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is 186 // removed. 187 if (is_observed_) { 188 BrowserThread::PostTask( 189 source_thread_id_, 190 FROM_HERE, 191 base::Bind(&ImporterList::SourceProfilesLoaded, this, profiles)); 192 } else { 193 source_profiles_.assign(profiles.begin(), profiles.end()); 194 source_profiles_loaded_ = true; 195 } 196 } 197 198 void ImporterList::SourceProfilesLoaded( 199 const std::vector<importer::SourceProfile*>& profiles) { 200 // |observer_| may be NULL if it removed itself before being notified. 201 if (!observer_) 202 return; 203 204 BrowserThread::ID current_thread_id; 205 BrowserThread::GetCurrentThreadIdentifier(¤t_thread_id); 206 DCHECK_EQ(current_thread_id, source_thread_id_); 207 208 source_profiles_.assign(profiles.begin(), profiles.end()); 209 source_profiles_loaded_ = true; 210 source_thread_id_ = BrowserThread::UI; 211 212 observer_->OnSourceProfilesLoaded(); 213 observer_ = NULL; 214 215 // TODO(jhawkins): Remove once DetectSourceProfilesHack is removed. 216 is_observed_ = false; 217 } 218