Get refcode on MacOS from xattr.

This commit is contained in:
mkarolin
2023-09-28 16:09:31 -04:00
committed by Max Karolinskiy
parent 53b7d0714f
commit 18fa76b2fa
6 changed files with 195 additions and 0 deletions
@@ -29,6 +29,13 @@ static_library("browser") {
"//services/network/public/cpp",
]
if (is_mac) {
sources += [
"file_extended_attribute.cc",
"file_extended_attribute.h",
]
}
if (is_android) {
sources += [
"android_brave_referrer.cc",
@@ -47,3 +54,19 @@ if (is_android) {
sources = [ "//brave/android/java/org/chromium/chrome/browser/util/BraveReferrer.java" ]
}
}
source_set("unit_tests") {
testonly = true
sources = []
deps = []
if (is_mac) {
sources += [ "file_extended_attribute_unittest.cc" ]
deps += [
":browser",
"//base",
"//base/test:test_support",
"//testing/gtest",
]
}
}
@@ -15,6 +15,7 @@
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -26,6 +27,7 @@
#include "brave/components/constants/network_constants.h"
#include "brave/components/constants/pref_names.h"
#include "brave_base/random.h"
#include "build/build_config.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/url_matcher/url_matcher.h"
@@ -40,6 +42,11 @@
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#if BUILDFLAG(IS_MAC)
#include "base/apple/bundle_locations.h"
#include "brave/components/brave_referrals/browser/file_extended_attribute.h"
#endif // BUILDFLAG(IS_MAC)
// Perform finalization checks once a day.
const int kFinalizationChecksFrequency = 60 * 60 * 24;
@@ -125,9 +132,46 @@ void DeletePromoCodeFile(const base::FilePath& promo_code_file) {
}
}
#if BUILDFLAG(IS_MAC)
std::string ReadPromoCodeFromXattr() {
static constexpr char kRefCodeAttr[] = "com.brave.refcode";
base::FilePath bundle_path = base::apple::OuterBundlePath();
std::vector<char> value;
int result_errno =
brave::GetFileExtendedAttribute(bundle_path, kRefCodeAttr, &value);
if (result_errno == ENOATTR) {
VLOG(0) << "Could not get promo code from " << bundle_path
<< ". The extended attribute " << kRefCodeAttr << " was not found.";
} else if (result_errno != 0) {
VLOG(0) << "Could not get promo code from " << bundle_path
<< ". An error occurred getting value for attribute "
<< kRefCodeAttr << ". Error code: " << result_errno << ".";
} else {
std::string promo_code(value.begin(), value.end());
base::TrimWhitespaceASCII(promo_code, base::TRIM_ALL, &promo_code);
if (promo_code.empty()) {
VLOG(0) << "Promo code value from " << bundle_path
<< "'s extended attribute " << kRefCodeAttr << " is empty.";
} else {
DVLOG(1) << "Promo code from " << kRefCodeAttr << ": " << promo_code;
return promo_code;
}
}
return "";
}
#endif // BUILDFLAG(IS_MAC)
std::string ReadPromoCode(const base::FilePath& promo_code_file) {
std::string promo_code;
#if BUILDFLAG(IS_MAC)
promo_code = ReadPromoCodeFromXattr();
if (!promo_code.empty()) {
return promo_code;
}
#endif // BUILDFLAG(IS_MAC)
if (!base::PathExists(promo_code_file)) {
return kDefaultPromoCode;
}
@@ -0,0 +1,39 @@
/* Copyright (c) 2023 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/components/brave_referrals/browser/file_extended_attribute.h"
#include <sys/xattr.h>
#include "base/logging.h"
namespace brave {
int GetFileExtendedAttribute(const base::FilePath& path,
const char* name,
std::vector<char>* value) {
// Pass nullptr for value to retrieve the length needed.
ssize_t expected_length =
getxattr(path.value().c_str(), name, /*value=*/nullptr,
/*size =*/0, /*position=*/0, /*options=*/0);
if (expected_length < 0) {
return errno;
}
value->resize(expected_length);
ssize_t length = getxattr(path.value().c_str(), name, value->data(),
expected_length, /*position=*/0,
/*options=*/0);
if (length != expected_length) {
VLOG(0) << "Failed to retrieve extended attribute " << name << " from file "
<< path << ". The expected data length (" << expected_length
<< ") and actual data length (" << length << ") do not match.";
return ENODATA;
}
return 0;
}
} // namespace brave
@@ -0,0 +1,28 @@
/* Copyright (c) 2023 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_BRAVE_REFERRALS_BROWSER_FILE_EXTENDED_ATTRIBUTE_H_
#define BRAVE_COMPONENTS_BRAVE_REFERRALS_BROWSER_FILE_EXTENDED_ATTRIBUTE_H_
#include <vector>
#include "base/files/file_path.h"
namespace brave {
// Extracts the value of an extended file attribute specified by |name| from the
// file specified by the |path|. The result is placed in the |value|. On
// success returns 0. Otherwise, returns ERRNO value. Error values of
// interest:
// ENOATTR - the attribute with the given |name| was not found.
// ENOTSUP - the file system doesn't support (or disabled) extended attributes.
// ENODATA - the value could not be retrieved.
int GetFileExtendedAttribute(const base::FilePath& path,
const char* name,
std::vector<char>* value);
} // namespace brave
#endif // BRAVE_COMPONENTS_BRAVE_REFERRALS_BROWSER_FILE_EXTENDED_ATTRIBUTE_H_
@@ -0,0 +1,60 @@
/* Copyright (c) 2023 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include <sys/xattr.h>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "brave/components/brave_referrals/browser/file_extended_attribute.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
constexpr char kXattrName[] = "com.brave.refcode";
constexpr char kXattrValue[] = "0xDEADFACE";
} // namespace
class BraveFileExtendedAttributeTest : public testing::Test {
public:
BraveFileExtendedAttributeTest() = default;
~BraveFileExtendedAttributeTest() override = default;
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(
base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &test_file_path_));
ASSERT_EQ(0,
setxattr(test_file_path_.value().c_str(), kXattrName, kXattrValue,
strlen(kXattrValue), /*position=*/0, /*options=*/0));
}
void TearDown() override { base::DeletePathRecursively(temp_dir_.GetPath()); }
const base::FilePath& test_file_path() { return test_file_path_; }
private:
base::ScopedTempDir temp_dir_;
base::FilePath test_file_path_;
};
TEST_F(BraveFileExtendedAttributeTest, GetPromoCodeAttribute) {
std::vector<char> value;
// Test file has this extended attribute
int result_errno =
brave::GetFileExtendedAttribute(test_file_path(), kXattrName, &value);
EXPECT_EQ(0, result_errno);
std::string xattr_value(value.begin(), value.end());
EXPECT_EQ(kXattrValue, xattr_value);
}
TEST_F(BraveFileExtendedAttributeTest, GetNonexistentAttribute) {
std::vector<char> value;
// Test file does NOT have this extended attribute
int result_errno = brave::GetFileExtendedAttribute(
test_file_path(), "com.brave.MadSheep", &value);
EXPECT_EQ(ENOATTR, result_errno);
}
+1
View File
@@ -206,6 +206,7 @@ test("brave_unit_tests") {
"//brave/components/brave_news/browser/test:brave_news_unit_tests",
"//brave/components/brave_perf_predictor/browser",
"//brave/components/brave_private_cdn",
"//brave/components/brave_referrals/browser:unit_tests",
"//brave/components/brave_rewards/common",
"//brave/components/brave_rewards/common:features",
"//brave/components/brave_rewards/core/test",