Skip to content

Commit

Permalink
Issue 6251: Backport firefox importer fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Efremov committed Nov 4, 2019
1 parent b5f0013 commit d804c06
Show file tree
Hide file tree
Showing 6 changed files with 480 additions and 17 deletions.
26 changes: 21 additions & 5 deletions patches/chrome-browser-importer-importer_list.cc.patch
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
index e557e55bdacf3164232e329389da9631cade8e93..613cd4fd78321310eed78cbb336c9eb1bd2f82c9 100644
index e557e55bdacf3164232e329389da9631cade8e93..f613af5207e550b91fb878d7fe56204fbdaecbc7 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -29,6 +29,9 @@
Expand Down Expand Up @@ -29,24 +29,40 @@ index e557e55bdacf3164232e329389da9631cade8e93..613cd4fd78321310eed78cbb336c9eb1
- if (importer::EdgeImporterCanImport())
+ if (shell_integration::IsIEDefaultBrowser()) {
+ DetectIEProfiles(profiles);
+ DetectEdgeProfiles(profiles);
+ } else {
DetectEdgeProfiles(profiles);
- DetectIEProfiles(profiles);
+ } else {
+ DetectEdgeProfiles(profiles);
+ DetectIEProfiles(profiles);
+ }
}

#endif // defined(OS_WIN)
@@ -122,6 +130,7 @@ void DetectFirefoxProfiles(const std::string locale,
@@ -89,8 +97,13 @@ void DetectFirefoxProfiles(const std::string locale,
std::vector<importer::SourceProfile>* profiles) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
-
- base::FilePath profile_path = GetFirefoxProfilePath();
+#if defined(OS_WIN)
+ const std::string firefox_install_id =
+ shell_integration::GetFirefoxProgIdSuffix();
+#else
+ const std::string firefox_install_id;
+#endif // defined(OS_WIN)
+ base::FilePath profile_path = GetFirefoxProfilePath(firefox_install_id);
if (profile_path.empty())
return;

@@ -122,6 +135,7 @@ void DetectFirefoxProfiles(const std::string locale,
firefox.app_path = app_path;
firefox.services_supported = importer::HISTORY | importer::FAVORITES |
importer::PASSWORDS | importer::SEARCH_ENGINES |
+ importer::COOKIES |
importer::AUTOFILL_FORM_DATA;
firefox.locale = locale;
profiles->push_back(firefox);
@@ -140,21 +149,37 @@ std::vector<importer::SourceProfile> DetectSourceProfilesWorker(
@@ -140,21 +154,37 @@ std::vector<importer::SourceProfile> DetectSourceProfilesWorker(
#if defined(OS_WIN)
if (shell_integration::IsFirefoxDefaultBrowser()) {
DetectFirefoxProfiles(locale, &profiles);
Expand Down
11 changes: 9 additions & 2 deletions patches/chrome-browser-shell_integration.h.patch
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index a7bd5219a9b9a433036db3a82e579c53158ce798..fdb4c9d1d59009577d4521ba32374984b109e864 100644
index a7bd5219a9b9a433036db3a82e579c53158ce798..c4e668791cf82b6269634c5a97381aae3b58034e 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -92,6 +92,12 @@ DefaultWebClientState GetDefaultBrowser();
@@ -92,6 +92,19 @@ DefaultWebClientState GetDefaultBrowser();
// user. This method is very fast so it can be invoked in the UI thread.
bool IsFirefoxDefaultBrowser();

+#if defined(OS_WIN)
+// Returns true if IE is likely to be the default browser for the current
+// user. This method is very fast so it can be invoked in the UI thread.
+bool IsIEDefaultBrowser();
+
+// Returns the install id of the installation set as default browser. If no
+// installation of Firefox is set as the default browser, returns an empty
+// string.
+// TODO(crbug/1011830): This should return the install id of the stable
+// version if no version of Firefox is set as default browser.
+std::string GetFirefoxProgIdSuffix();
+#endif
+
// Attempt to determine if this instance of Chrome is the default client
Expand Down
66 changes: 56 additions & 10 deletions patches/chrome-browser-shell_integration_win.cc.patch
Original file line number Diff line number Diff line change
@@ -1,19 +1,65 @@
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index 9b05880c7b94700e2cbfdddcd8e0b95cd11f7c4e..08e519ba345854aa29dc5927b58fe6325228e55d 100644
index 9b05880c7b94700e2cbfdddcd8e0b95cd11f7c4e..f6b4919378cc72bffe1e95d261566364e3a06e4b 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -588,6 +588,14 @@ bool IsFirefoxDefaultBrowser() {
app_cmd == L"FirefoxURL";
@@ -492,6 +492,15 @@ void IsPinnedToTaskbarHelper::OnIsPinnedToTaskbarResult(
delete this;
}

+bool IsIEDefaultBrowser() {
+ base::string16 app_cmd;
+base::string16 GetHttpProtocolUserChoiceProgId() {
+ base::string16 prog_id;
+ base::win::RegKey key(HKEY_CURRENT_USER, ShellUtil::kRegVistaUrlPrefs,
+ KEY_READ);
+ return key.Valid() && key.ReadValue(L"Progid", &app_cmd) == ERROR_SUCCESS &&
+ app_cmd == L"IE.HTTP";
+ KEY_QUERY_VALUE);
+ if (key.Valid())
+ key.ReadValue(L"ProgId", &prog_id);
+ return prog_id;
+}
+
} // namespace

bool SetAsDefaultBrowser() {
@@ -569,23 +578,28 @@ DefaultWebClientState GetDefaultBrowser() {
ShellUtil::GetChromeDefaultState());
}

-// There is no reliable way to say which browser is default on a machine (each
-// browser can have some of the protocols/shortcuts). So we look for only HTTP
-// protocol handler. Even this handler is located at different places in
-// registry on XP and Vista:
-// - HKCR\http\shell\open\command (XP)
-// - HKCU\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\
-// http\UserChoice (Vista)
-// This method checks if Firefox is default browser by checking these
-// locations and returns true if Firefox traces are found there. In case of
-// error (or if Firefox is not found)it returns the default value which
-// is false.
+// This method checks if Firefox is default browser by checking for the default
+// HTTP protocol handler. Returns false in case of error or if Firefox is not
+// the user's default http protocol client.
bool IsFirefoxDefaultBrowser() {
- base::string16 app_cmd;
- base::win::RegKey key(HKEY_CURRENT_USER, ShellUtil::kRegVistaUrlPrefs,
- KEY_READ);
- return key.Valid() && key.ReadValue(L"Progid", &app_cmd) == ERROR_SUCCESS &&
- app_cmd == L"FirefoxURL";
+ return base::StartsWith(GetHttpProtocolUserChoiceProgId(), L"FirefoxURL",
+ base::CompareCase::SENSITIVE);
+}
+
+std::string GetFirefoxProgIdSuffix() {
+ const base::string16 app_cmd = GetHttpProtocolUserChoiceProgId();
+ static constexpr base::StringPiece16 kFirefoxProgIdPrefix(L"FirefoxURL-");
+ if (base::StartsWith(app_cmd, kFirefoxProgIdPrefix,
+ base::CompareCase::SENSITIVE)) {
+ // Returns the id that appears after the prefix "FirefoxURL-".
+ return std::string(app_cmd.begin() + kFirefoxProgIdPrefix.size(),
+ app_cmd.end());
+ }
+ return std::string();
+}
+
+bool IsIEDefaultBrowser() {
+ return GetHttpProtocolUserChoiceProgId() == L"IE.HTTP";
}

DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) {
return GetDefaultWebClientStateFromShellUtilDefaultState(
ShellUtil::GetChromeDefaultProtocolClientState(
137 changes: 137 additions & 0 deletions patches/chrome-common-importer-firefox_importer_utils.cc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
diff --git a/chrome/common/importer/firefox_importer_utils.cc b/chrome/common/importer/firefox_importer_utils.cc
index e1f5ada77718755f5a59d78e63a14e500330e002..7360ca488a158b70c99f55c4ba170777a19d5181 100644
--- a/chrome/common/importer/firefox_importer_utils.cc
+++ b/chrome/common/importer/firefox_importer_utils.cc
@@ -50,51 +50,107 @@ base::FilePath GetProfilePath(const base::DictionaryValue& root,
return path;
}

-// Checks if the named profile is the default profile.
-bool IsDefaultProfile(const base::DictionaryValue& root,
- const std::string& profile_name) {
- std::string is_default;
- root.GetStringASCII(profile_name + ".Default", &is_default);
- return is_default == "1";
+// Returns a map from Firefox profiles to their corresponding installation ids.
+// The keys are file system paths for Firefox profiles that are the default
+// profile in their installation. The values are the registry keys for the
+// corresponding installation.
+std::map<std::string, std::string> GetDefaultProfilesPerInstall(
+ const base::DictionaryValue& root) {
+ std::map<std::string, std::string> default_profile_to_install_id;
+ static constexpr base::StringPiece kInstallPrefix("Install");
+ // Find the default profiles for each Firefox installation.
+ for (const auto& data : root) {
+ const std::string& dict_key = data.first;
+ if (base::StartsWith(dict_key, kInstallPrefix,
+ base::CompareCase::SENSITIVE)) {
+ std::string path;
+ if (root.GetStringASCII(dict_key + ".Default", &path)) {
+ default_profile_to_install_id.emplace(
+ std::move(path), dict_key.substr(kInstallPrefix.size()));
+ }
+ }
+ }
+ return default_profile_to_install_id;
+}
+
+base::FilePath GetLegacyDefaultProfilePath(
+ const base::DictionaryValue& root,
+ const std::vector<std::string>& profile_names) {
+ if (profile_names.empty())
+ return base::FilePath();
+
+ // When multiple profiles exist, the path to the default profile is returned.
+ for (const auto& profile_name : profile_names) {
+ // Checks if the named profile is the default profile using the legacy
+ // format of profiles.ini (Firefox version < 67).
+ std::string is_default;
+ if (root.GetStringASCII(profile_name + ".Default", &is_default) &&
+ is_default == "1") {
+ return GetProfilePath(root, profile_name);
+ }
+ }
+
+ // If no default profile is found, the path to Profile0 will be returned.
+ return GetProfilePath(root, profile_names.front());
}

} // namespace

-base::FilePath GetFirefoxProfilePath() {
+base::FilePath GetFirefoxProfilePath(const std::string& firefox_install_id) {
base::FilePath ini_file = GetProfilesINI();
std::string content;
base::ReadFileToString(ini_file, &content);
DictionaryValueINIParser ini_parser;
ini_parser.Parse(content);
- return GetFirefoxProfilePathFromDictionary(ini_parser.root());
+ return GetFirefoxProfilePathFromDictionary(ini_parser.root(),
+ firefox_install_id);
}

base::FilePath GetFirefoxProfilePathFromDictionary(
- const base::DictionaryValue& root) {
- std::vector<std::string> profiles;
+ const base::DictionaryValue& root,
+ const std::string& firefox_install_id) {
+ // List of profiles linked to a Firefox installation. This will be empty for
+ // Firefox versions older than 67.
+ std::map<std::string, std::string> default_profile_to_install_id =
+ GetDefaultProfilesPerInstall(root);
+ // First profile linked to a Firefox installation (version >= 67).
+ base::Optional<std::string> first_modern_profile;
+
+ // Profiles not linked to a Firefox installation (version < 67).
+ std::vector<std::string> legacy_profiles;
+
for (int i = 0; ; ++i) {
std::string current_profile = base::StringPrintf("Profile%d", i);
- if (root.HasKey(current_profile)) {
- profiles.push_back(current_profile);
- } else {
- // Profiles are continuously numbered. So we exit when we can't
+ if (!root.HasKey(current_profile)) {
+ // Profiles are contiguously numbered. So we exit when we can't
// find the i-th one.
break;
}
- }

- if (profiles.empty())
- return base::FilePath();
+ std::string path;
+ if (!root.GetStringASCII(current_profile + ".Path", &path))
+ continue;

- // When multiple profiles exist, the path to the default profile is returned,
- // since the other profiles are used mostly by developers for testing.
- for (std::vector<std::string>::const_iterator it = profiles.begin();
- it != profiles.end(); ++it)
- if (IsDefaultProfile(root, *it))
- return GetProfilePath(root, *it);
+ auto install_id_it = default_profile_to_install_id.find(path);
+ if (install_id_it != default_profile_to_install_id.end()) {
+ // If this installation is the default browser, use the associated
+ // profile as default profile.
+ if (install_id_it->second == firefox_install_id)
+ return GetProfilePath(root, current_profile);
+ if (!first_modern_profile)
+ first_modern_profile.emplace(std::move(current_profile));
+ } else {
+ // If no Firefox installation found in profiles.ini, legacy profiles
+ // (Firefox version < 67) are being used.
+ legacy_profiles.push_back(std::move(current_profile));
+ }
+ }

- // If no default profile is found, the path to Profile0 will be returned.
- return GetProfilePath(root, profiles.front());
+ // Take the first install found as the default install.
+ if (first_modern_profile)
+ return GetProfilePath(root, *first_modern_profile);
+
+ return GetLegacyDefaultProfilePath(root, legacy_profiles);
}

#if defined(OS_MACOSX)
25 changes: 25 additions & 0 deletions patches/chrome-common-importer-firefox_importer_utils.h.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
diff --git a/chrome/common/importer/firefox_importer_utils.h b/chrome/common/importer/firefox_importer_utils.h
index ec57c17927173691d98db394d726da41d1f43475..e9feec4eae2b73cea2b1c722095b4c121968aced 100644
--- a/chrome/common/importer/firefox_importer_utils.h
+++ b/chrome/common/importer/firefox_importer_utils.h
@@ -38,13 +38,17 @@ base::FilePath GetFirefoxInstallPathFromRegistry();
base::FilePath GetFirefoxDylibPath();
#endif // OS_MACOSX

-// Returns the path to the Firefox profile.
-base::FilePath GetFirefoxProfilePath();
+// Returns the path to the default profile of the Firefox installation with id
+// |firefox_install_id|.
+base::FilePath GetFirefoxProfilePath(const std::string& firefox_install_id);

// Returns the path to the Firefox profile, using a custom dictionary.
+// If |firefox_install_id| is not empty returns the default profile associated
+// with that id.
// Exposed for testing.
base::FilePath GetFirefoxProfilePathFromDictionary(
- const base::DictionaryValue& root);
+ const base::DictionaryValue& root,
+ const std::string& firefox_install_id);

// Detects version of Firefox and installation path for the given Firefox
// profile.
Loading

0 comments on commit d804c06

Please sign in to comment.