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 bool include_interactive_profiles, 110 importer::ImporterListObserver* observer) { 111 DCHECK(observer); 112 observer_ = observer; 113 is_observed_ = true; 114 115 bool res = BrowserThread::GetCurrentThreadIdentifier(&source_thread_id_); 116 DCHECK(res); 117 118 BrowserThread::PostTask(BrowserThread::FILE, 119 FROM_HERE, 120 base::Bind(&ImporterList::DetectSourceProfilesWorker, 121 this, 122 locale, 123 include_interactive_profiles)); 124 } 125 126 void ImporterList::DetectSourceProfilesHack(const std::string& locale, 127 bool include_interactive_profiles) { 128 DetectSourceProfilesWorker(locale, include_interactive_profiles); 129 } 130 131 const importer::SourceProfile& ImporterList::GetSourceProfileAt( 132 size_t index) const { 133 DCHECK(source_profiles_loaded_); 134 DCHECK_LT(index, count()); 135 return *source_profiles_[index]; 136 } 137 138 const importer::SourceProfile& ImporterList::GetSourceProfileForImporterType( 139 int importer_type) const { 140 DCHECK(source_profiles_loaded_); 141 142 for (size_t i = 0; i < count(); ++i) { 143 if (source_profiles_[i]->importer_type == importer_type) 144 return *source_profiles_[i]; 145 } 146 NOTREACHED(); 147 return *(new importer::SourceProfile); 148 } 149 150 ImporterList::~ImporterList() { 151 } 152 153 void ImporterList::DetectSourceProfilesWorker( 154 const std::string& locale, 155 bool include_interactive_profiles) { 156 // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is 157 // removed. 158 if (is_observed_) 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 160 161 std::vector<importer::SourceProfile*> profiles; 162 163 // The first run import will automatically take settings from the first 164 // profile detected, which should be the user's current default. 165 #if defined(OS_WIN) 166 if (ShellIntegration::IsFirefoxDefaultBrowser()) { 167 DetectFirefoxProfiles(locale, &profiles); 168 DetectIEProfiles(&profiles); 169 } else { 170 DetectIEProfiles(&profiles); 171 DetectFirefoxProfiles(locale, &profiles); 172 } 173 #elif defined(OS_MACOSX) 174 if (ShellIntegration::IsFirefoxDefaultBrowser()) { 175 DetectFirefoxProfiles(locale, &profiles); 176 DetectSafariProfiles(&profiles); 177 } else { 178 DetectSafariProfiles(&profiles); 179 DetectFirefoxProfiles(locale, &profiles); 180 } 181 #else 182 DetectFirefoxProfiles(locale, &profiles); 183 #endif 184 if (include_interactive_profiles) { 185 importer::SourceProfile* bookmarks_profile = new importer::SourceProfile; 186 bookmarks_profile->importer_name = 187 l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE); 188 bookmarks_profile->importer_type = importer::TYPE_BOOKMARKS_FILE; 189 bookmarks_profile->services_supported = importer::FAVORITES; 190 profiles.push_back(bookmarks_profile); 191 } 192 193 // TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is 194 // removed. 195 if (is_observed_) { 196 BrowserThread::PostTask( 197 source_thread_id_, 198 FROM_HERE, 199 base::Bind(&ImporterList::SourceProfilesLoaded, this, profiles)); 200 } else { 201 source_profiles_.assign(profiles.begin(), profiles.end()); 202 source_profiles_loaded_ = true; 203 } 204 } 205 206 void ImporterList::SourceProfilesLoaded( 207 const std::vector<importer::SourceProfile*>& profiles) { 208 // |observer_| may be NULL if it removed itself before being notified. 209 if (!observer_) 210 return; 211 212 BrowserThread::ID current_thread_id; 213 BrowserThread::GetCurrentThreadIdentifier(¤t_thread_id); 214 DCHECK_EQ(current_thread_id, source_thread_id_); 215 216 source_profiles_.assign(profiles.begin(), profiles.end()); 217 source_profiles_loaded_ = true; 218 source_thread_id_ = BrowserThread::UI; 219 220 observer_->OnSourceProfilesLoaded(); 221 observer_ = NULL; 222 223 // TODO(jhawkins): Remove once DetectSourceProfilesHack is removed. 224 is_observed_ = false; 225 } 226