Added functionality such that on Linux, after downloading a file,

the source URL and referrer URL are stored as extended file attributes.

Also see http://www.freedesktop.org/wiki/CommonExtendedAttributes

BUG=45903
TEST=content_unittests/file_metadata_unittest_linux.cc/FileMetadataLinuxTest

Review URL: https://chromiumcodereview.appspot.com/10784007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148729 0039d316-1c4b-4281-b951-d872f2087c98
parent d0fb4db3
......@@ -27,6 +27,8 @@
#include "content/browser/safe_util_win.h"
#elif defined(OS_MACOSX)
#include "content/browser/file_metadata_mac.h"
#elif defined(OS_LINUX)
#include "content/browser/download/file_metadata_linux.h"
#endif
using content::BrowserThread;
......@@ -470,6 +472,8 @@ void BaseFile::AnnotateWithSourceInformation() {
referrer_url_);
file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
referrer_url_);
#elif defined(OS_LINUX)
content::AddOriginMetadataToFile(full_path_, source_url_, referrer_url_);
#endif
}
......@@ -555,3 +559,4 @@ int64 BaseFile::CurrentSpeed() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
return CurrentSpeedAtTime(base::TimeTicks::Now());
}
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/download/file_metadata_linux.h"
#include <sys/types.h>
#include <sys/xattr.h>
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "googleurl/src/gurl.h"
namespace content {
const char kSourceURLAttrName[] = "user.xdg.origin.url";
const char kReferrerURLAttrName[] = "user.xdg.referrer.url";
static void SetExtendedFileAttribute(const char* path, const char* name,
const char* value, size_t value_size,
int flags) {
int result = setxattr(path, name, value, value_size, flags);
if (result) {
DPLOG(ERROR)
<< "Could not set extended attribute " << name << " on file " << path;
}
}
void AddOriginMetadataToFile(const FilePath& file, const GURL& source,
const GURL& referrer) {
DCHECK(file_util::PathIsWritable(file));
if (source.is_valid()) {
SetExtendedFileAttribute(file.value().c_str(), kSourceURLAttrName,
source.spec().c_str(), source.spec().length(), 0);
}
if (referrer.is_valid()) {
SetExtendedFileAttribute(file.value().c_str(), kReferrerURLAttrName,
referrer.spec().c_str(), referrer.spec().length(), 0);
}
}
} // namespace file_metadata
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_DOWNLOAD_FILE_METADATA_LINUX_H_
#define CONTENT_BROWSER_DOWNLOAD_FILE_METADATA_LINUX_H_
#include "content/common/content_export.h"
class FilePath;
class GURL;
namespace content {
// The source URL attribute is part of the XDG standard.
// The referrer URL attribute is not part of the XDG standard,
// but it is used to keep the naming consistent.
// http://freedesktop.org/wiki/CommonExtendedAttributes
CONTENT_EXPORT extern const char kSourceURLAttrName[];
CONTENT_EXPORT extern const char kReferrerURLAttrName[];
// Adds origin metadata to the file.
// |source| should be the source URL for the download, and |referrer| should be
// the URL the user initiated the download from.
CONTENT_EXPORT void AddOriginMetadataToFile(const FilePath& file,
const GURL& source,
const GURL& referrer);
} // namespace file_metadata
#endif // CONTENT_BROWSER_DOWNLOAD_FILE_METADATA_LINUX_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <errno.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <algorithm>
#include <sstream>
#include <string>
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_temp_dir.h"
#include "base/string_split.h"
#include "content/browser/download/file_metadata_linux.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
using std::istringstream;
using std::string;
using std::vector;
class FileMetadataLinuxTest : public testing::Test {
public:
FileMetadataLinuxTest()
: source_url_("http://www.source.com"),
referrer_url_("http://www.referrer.com") {}
const FilePath& test_file() const {
return test_file_;
}
const GURL& source_url() const {
return source_url_;
}
const GURL& referrer_url() const {
return referrer_url_;
}
bool is_xattr_supported() const {
return is_xattr_supported_;
}
protected:
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
&test_file_));
int result = setxattr(test_file_.value().c_str(),
"user.test", "test", 4, 0);
is_xattr_supported_ = (!result) || (errno != ENOTSUP);
if (!is_xattr_supported_) {
LOG(INFO) << "Test will be skipped because extended attributes are not "
<< "supported on this OS/file system.";
}
}
void CheckExtendedAttributeValue(const string attr_name,
const string expected_value) const {
ssize_t len = getxattr(test_file().value().c_str(), attr_name.c_str(),
NULL, 0);
if (len <= static_cast<ssize_t>(0)) {
FAIL() << "Attribute '" << attr_name << "' does not exist";
}
char* buffer = new char[len];
len = getxattr(test_file().value().c_str(), attr_name.c_str(), buffer, len);
EXPECT_EQ(expected_value.size(), static_cast<size_t>(len));
string real_value(buffer, len);
delete[] buffer;
EXPECT_EQ(expected_value, real_value);
}
void GetExtendedAttributeNames(vector<string>* attr_names) const {
ssize_t len = listxattr(test_file().value().c_str(), NULL, 0);
if (len <= static_cast<ssize_t>(0)) return;
char* buffer = new char[len];
len = listxattr(test_file().value().c_str(), buffer, len);
attr_names->clear();
base::SplitString(string(buffer, len), '\0', attr_names);
delete[] buffer;
}
void VerifyAttributesAreSetCorrectly() const {
vector<string> attr_names;
GetExtendedAttributeNames(&attr_names);
// Check if the attributes are set on the file
vector<string>::const_iterator pos = find(attr_names.begin(),
attr_names.end(), content::kSourceURLAttrName);
EXPECT_NE(pos, attr_names.end());
pos = find(attr_names.begin(), attr_names.end(),
content::kReferrerURLAttrName);
EXPECT_NE(pos, attr_names.end());
// Check if the attribute values are set correctly
CheckExtendedAttributeValue(content::kSourceURLAttrName,
source_url().spec());
CheckExtendedAttributeValue(content::kReferrerURLAttrName,
referrer_url().spec());
}
private:
ScopedTempDir temp_dir_;
FilePath test_file_;
GURL source_url_;
GURL referrer_url_;
bool is_xattr_supported_;
};
TEST_F(FileMetadataLinuxTest, CheckMetadataSetCorrectly) {
if (!is_xattr_supported()) return;
content::AddOriginMetadataToFile(test_file(), source_url(), referrer_url());
VerifyAttributesAreSetCorrectly();
}
TEST_F(FileMetadataLinuxTest, SetMetadataMultipleTimes) {
if (!is_xattr_supported()) return;
content::AddOriginMetadataToFile(test_file(),
GURL("http://www.dummy.com"), GURL("http://www.dummy.com"));
content::AddOriginMetadataToFile(test_file(), source_url(), referrer_url());
VerifyAttributesAreSetCorrectly();
}
TEST_F(FileMetadataLinuxTest, InvalidSourceURLTest) {
if (!is_xattr_supported()) return;
GURL invalid_url;
vector<string> attr_names;
content::AddOriginMetadataToFile(test_file(), invalid_url, referrer_url());
GetExtendedAttributeNames(&attr_names);
EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
content::kSourceURLAttrName));
CheckExtendedAttributeValue(content::kReferrerURLAttrName,
referrer_url().spec());
}
TEST_F(FileMetadataLinuxTest, InvalidReferrerURLTest) {
if (!is_xattr_supported()) return;
GURL invalid_url;
vector<string> attr_names;
content::AddOriginMetadataToFile(test_file(), source_url(), invalid_url);
GetExtendedAttributeNames(&attr_names);
EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
content::kReferrerURLAttrName));
CheckExtendedAttributeValue(content::kSourceURLAttrName, source_url().spec());
}
TEST_F(FileMetadataLinuxTest, InvalidURLsTest) {
if (!is_xattr_supported()) return;
GURL invalid_url;
vector<string> attr_names;
content::AddOriginMetadataToFile(test_file(), invalid_url, invalid_url);
GetExtendedAttributeNames(&attr_names);
EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
content::kSourceURLAttrName));
EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
content::kReferrerURLAttrName));
}
} // namespace
......@@ -318,6 +318,8 @@
'browser/download/drag_download_file.h',
'browser/download/drag_download_util.cc',
'browser/download/drag_download_util.h',
'browser/download/file_metadata_linux.cc',
'browser/download/file_metadata_linux.h',
'browser/download/mhtml_generation_manager.cc',
'browser/download/mhtml_generation_manager.h',
'browser/download/save_file.cc',
......
......@@ -253,6 +253,7 @@
'browser/download/download_id_unittest.cc',
'browser/download/download_item_impl_unittest.cc',
'browser/download/download_manager_impl_unittest.cc',
'browser/download/file_metadata_unittest_linux.cc',
'browser/download/save_package_unittest.cc',
'browser/gamepad/gamepad_provider_unittest.cc',
'browser/geolocation/device_data_provider_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment