diff options
author | cristian.patrasciuc@gmail.com <cristian.patrasciuc@gmail.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 08:03:55 +0000 |
---|---|---|
committer | cristian.patrasciuc@gmail.com <cristian.patrasciuc@gmail.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 08:03:55 +0000 |
commit | 6153ad9d42b202335a534c72b6d72de0f74017ce (patch) | |
tree | 2b843a753dea190f37d7e78204b8cf8cc65f9ca5 /content | |
parent | d0fb4db3f54da52a7fc5fd7ac3c7b1a2e25b9de9 (diff) | |
download | chromium_src-6153ad9d42b202335a534c72b6d72de0f74017ce.zip chromium_src-6153ad9d42b202335a534c72b6d72de0f74017ce.tar.gz chromium_src-6153ad9d42b202335a534c72b6d72de0f74017ce.tar.bz2 |
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
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/download/base_file.cc | 5 | ||||
-rw-r--r-- | content/browser/download/file_metadata_linux.cc | 43 | ||||
-rw-r--r-- | content/browser/download/file_metadata_linux.h | 31 | ||||
-rw-r--r-- | content/browser/download/file_metadata_unittest_linux.cc | 165 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/content_tests.gypi | 1 |
6 files changed, 247 insertions, 0 deletions
diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc index 396ac33..786e78c 100644 --- a/content/browser/download/base_file.cc +++ b/content/browser/download/base_file.cc @@ -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()); } + diff --git a/content/browser/download/file_metadata_linux.cc b/content/browser/download/file_metadata_linux.cc new file mode 100644 index 0000000..5beece5 --- /dev/null +++ b/content/browser/download/file_metadata_linux.cc @@ -0,0 +1,43 @@ +// 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 diff --git a/content/browser/download/file_metadata_linux.h b/content/browser/download/file_metadata_linux.h new file mode 100644 index 0000000..b735f6e --- /dev/null +++ b/content/browser/download/file_metadata_linux.h @@ -0,0 +1,31 @@ +// 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_ diff --git a/content/browser/download/file_metadata_unittest_linux.cc b/content/browser/download/file_metadata_unittest_linux.cc new file mode 100644 index 0000000..40ed3e5 --- /dev/null +++ b/content/browser/download/file_metadata_unittest_linux.cc @@ -0,0 +1,165 @@ +// 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 diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 744758b..074a209 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -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', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index d897ef5..0430378 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -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', |