Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport importer bugfixes #3837

Merged
merged 2 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 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..d622e086ab259a8989b774f4788cba7bfe348092 100644
index e557e55bdacf3164232e329389da9631cade8e93..f613af5207e550b91fb878d7fe56204fbdaecbc7 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -29,6 +29,9 @@
Expand All @@ -12,15 +12,57 @@ index e557e55bdacf3164232e329389da9631cade8e93..d622e086ab259a8989b774f4788cba7b
namespace {

#if defined(OS_WIN)
@@ -122,6 +125,7 @@ void DetectFirefoxProfiles(const std::string locale,
@@ -47,6 +50,8 @@ void DetectIEProfiles(std::vector<importer::SourceProfile>* profiles) {
}

void DetectEdgeProfiles(std::vector<importer::SourceProfile>* profiles) {
+ if (!importer::EdgeImporterCanImport())
+ return;
importer::SourceProfile edge;
edge.importer_name = l10n_util::GetStringUTF16(IDS_IMPORT_FROM_EDGE);
edge.importer_type = importer::TYPE_EDGE;
@@ -57,10 +62,13 @@ void DetectEdgeProfiles(std::vector<importer::SourceProfile>* profiles) {

void DetectBuiltinWindowsProfiles(
std::vector<importer::SourceProfile>* profiles) {
- // Make the assumption on Windows 10 that Edge exists and is probably default.
- if (importer::EdgeImporterCanImport())
+ if (shell_integration::IsIEDefaultBrowser()) {
+ DetectIEProfiles(profiles);
+ DetectEdgeProfiles(profiles);
+ } else {
DetectEdgeProfiles(profiles);
- DetectIEProfiles(profiles);
+ DetectIEProfiles(profiles);
+ }
}

#endif // defined(OS_WIN)
@@ -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 +144,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
24 changes: 24 additions & 0 deletions patches/chrome-browser-shell_integration.h.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index a7bd5219a9b9a433036db3a82e579c53158ce798..c4e668791cf82b6269634c5a97381aae3b58034e 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -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
// application for the given protocol and return the appropriate state.
DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol);
65 changes: 65 additions & 0 deletions patches/chrome-browser-shell_integration_win.cc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index 9b05880c7b94700e2cbfdddcd8e0b95cd11f7c4e..f6b4919378cc72bffe1e95d261566364e3a06e4b 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -492,6 +492,15 @@ void IsPinnedToTaskbarHelper::OnIsPinnedToTaskbarResult(
delete this;
}

+base::string16 GetHttpProtocolUserChoiceProgId() {
+ base::string16 prog_id;
+ base::win::RegKey key(HKEY_CURRENT_USER, ShellUtil::kRegVistaUrlPrefs,
+ 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) {
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