| // Copyright 2016 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/base_file.h" |
| |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "content/public/browser/download_interrupt_reasons.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "net/base/filename_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| TEST(BaseFileWin, AnnotateWithSourceInformation) { |
| const base::FilePath::CharType kZoneIdentifierStreamName[] = |
| FILE_PATH_LITERAL(":Zone.Identifier"); |
| const char kInternetZoneIdentifierString[] = "[ZoneTransfer]\r\nZoneId=3\r\n"; |
| |
| struct { |
| const char* const url; |
| const char* const referrer; |
| bool expected_internet_zone; |
| } kTestCases[] = { |
| // Test cases where we expect a MOTW. |
| {"http://example.com", "http://example.com", true}, |
| {"", "http://example.com", true}, |
| {"", "", true}, |
| {"http://example.com", "", true}, |
| {"data:text/plain,Foo", "http://example.com", true}, |
| {"data:text/plain,Foo", "", true}, |
| {"data:text/plain,Foo", "data:text/plain,Bar", true}, |
| {"data:text/plain,Foo", "ftp://localhost/foo", true}, |
| {"http://example.com", "http://localhost/foo", true}, |
| {"ftp://example.com/foo", "", true}, |
| |
| // Test cases where we don't expect a MOTW. These test cases result in |
| // different behavior across Windows versions. |
| {"ftp://localhost/foo", "", false}, |
| {"http://localhost/foo", "", false}, |
| {"", "http://localhost/foo", false}, |
| {"file:///exists.txt", "", false}, |
| {"file:///exists.txt", "http://example.com", false}, |
| {"file:///does-not-exist.txt", "", false}, |
| }; |
| |
| content::TestBrowserThreadBundle threads; |
| base::ScopedTempDir target_directory; |
| ASSERT_TRUE(target_directory.CreateUniqueTempDir()); |
| |
| ASSERT_EQ(6, |
| base::WriteFile(target_directory.path().AppendASCII("exists.txt"), |
| "Exists", 6)); |
| |
| for (const auto& test_case : kTestCases) { |
| GURL url(test_case.url); |
| GURL referrer(test_case.referrer); |
| |
| // Resolve file:// URLs relative to our temp directory. |
| if (url.SchemeIsFile()) { |
| base::FilePath relative_path = |
| base::FilePath().AppendASCII(url.path().substr(1)); |
| url = |
| net::FilePathToFileURL(target_directory.path().Append(relative_path)); |
| } |
| |
| SCOPED_TRACE(::testing::Message() << "Source URL: " << url.spec() |
| << " Referrer: " << test_case.referrer); |
| |
| BaseFile base_file((net::NetLogWithSource())); |
| ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| base_file.Initialize(base::FilePath(), target_directory.path(), |
| base::File(), 0, std::string(), |
| std::unique_ptr<crypto::SecureHash>())); |
| ASSERT_FALSE(base_file.full_path().empty()); |
| ASSERT_EQ( |
| DOWNLOAD_INTERRUPT_REASON_NONE, |
| base_file.Rename(target_directory.path().AppendASCII("test_file.doc"))); |
| ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| base_file.AnnotateWithSourceInformation( |
| "7B2CEE7C-DC81-4160-86F1-9C968597118F", url, referrer)); |
| base_file.Detach(); |
| base_file.Finish(); |
| |
| base::FilePath path = base_file.full_path(); |
| base::FilePath zone_identifier_stream(path.value() + |
| kZoneIdentifierStreamName); |
| |
| ASSERT_TRUE(base::PathExists(path)); |
| |
| std::string zone_identifier; |
| base::ReadFileToString(zone_identifier_stream, &zone_identifier); |
| |
| if (test_case.expected_internet_zone) { |
| EXPECT_STREQ(kInternetZoneIdentifierString, zone_identifier.c_str()); |
| } else { |
| // Seeing an unexpected zone identifier is not an error, but we log a |
| // warning just the same so that such cases can be identified during |
| // manual testing. |
| if (zone_identifier == kInternetZoneIdentifierString) { |
| LOG(WARNING) << "Unexpected internet zone annotation for Source:" |
| << url.spec() << " Referrer:" << test_case.referrer; |
| } else if (!zone_identifier.empty()) { |
| LOG(WARNING) << "Unexpected zone annotation for Source:" << url.spec() |
| << " Referrer:" << test_case.referrer |
| << " Annotation:" << std::endl |
| << zone_identifier; |
| } |
| } |
| base::DeleteFile(path, false); |
| } |
| } |
| |
| } // namespace content |