diff options
author | Zeno Albisser <zeno.albisser@theqtcompany.com> | 2014-12-05 15:04:29 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@theqtcompany.com> | 2014-12-09 10:49:28 +0100 |
commit | af6588f8d723931a298c995fa97259bb7f7deb55 (patch) | |
tree | 060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/net/base | |
parent | 2fff84d821cc7b1c785f6404e0f8091333283e74 (diff) | |
download | qtwebengine-chromium-af6588f8d723931a298c995fa97259bb7f7deb55.tar.gz |
BASELINE: Update chromium to 40.0.2214.28 and ninja to 1.5.3.
Change-Id: I759465284fd64d59ad120219cbe257f7402c4181
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/net/base')
122 files changed, 7367 insertions, 3265 deletions
diff --git a/chromium/net/base/address_list_unittest.cc b/chromium/net/base/address_list_unittest.cc index 32c3e521642..e5597885bdc 100644 --- a/chromium/net/base/address_list_unittest.cc +++ b/chromium/net/base/address_list_unittest.cc @@ -121,7 +121,7 @@ TEST(AddressListTest, CreateFromIPAddressList) { // Construct a list of ip addresses. IPAddressList ip_list; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { IPAddressNumber ip_number; ASSERT_TRUE(ParseIPLiteralToNumber(tests[i].ip_address, &ip_number)); ip_list.push_back(ip_number); @@ -131,7 +131,7 @@ TEST(AddressListTest, CreateFromIPAddressList) { kCanonicalName); std::string canonical_name; EXPECT_EQ(kCanonicalName, test_list.canonical_name()); - EXPECT_EQ(ARRAYSIZE_UNSAFE(tests), test_list.size()); + EXPECT_EQ(arraysize(tests), test_list.size()); } } // namespace diff --git a/chromium/net/base/address_tracker_linux.cc b/chromium/net/base/address_tracker_linux.cc index 36738136695..27dd2019ab0 100644 --- a/chromium/net/base/address_tracker_linux.cc +++ b/chromium/net/base/address_tracker_linux.cc @@ -97,6 +97,18 @@ const char* GetInterfaceName(int interface_index) { } // namespace +AddressTrackerLinux::AddressTrackerLinux() + : get_interface_name_(GetInterfaceName), + address_callback_(base::Bind(&base::DoNothing)), + link_callback_(base::Bind(&base::DoNothing)), + tunnel_callback_(base::Bind(&base::DoNothing)), + netlink_fd_(-1), + is_offline_(true), + is_offline_initialized_(false), + is_offline_initialized_cv_(&is_offline_lock_), + tracking_(false) { +} + AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback, const base::Closure& link_callback, const base::Closure& tunnel_callback) @@ -107,7 +119,8 @@ AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback, netlink_fd_(-1), is_offline_(true), is_offline_initialized_(false), - is_offline_initialized_cv_(&is_offline_lock_) { + is_offline_initialized_cv_(&is_offline_lock_), + tracking_(true) { DCHECK(!address_callback.is_null()); DCHECK(!link_callback.is_null()); } @@ -124,20 +137,24 @@ void AddressTrackerLinux::Init() { return; } - // Request notifications. - struct sockaddr_nl addr = {}; - addr.nl_family = AF_NETLINK; - addr.nl_pid = getpid(); - // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993 - addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | - RTMGRP_LINK; - int rv = bind(netlink_fd_, - reinterpret_cast<struct sockaddr*>(&addr), - sizeof(addr)); - if (rv < 0) { - PLOG(ERROR) << "Could not bind NETLINK socket"; - AbortAndForceOnline(); - return; + int rv; + + if (tracking_) { + // Request notifications. + struct sockaddr_nl addr = {}; + addr.nl_family = AF_NETLINK; + addr.nl_pid = getpid(); + // TODO(szym): Track RTMGRP_LINK as well for ifi_type, + // http://crbug.com/113993 + addr.nl_groups = + RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK; + rv = bind( + netlink_fd_, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)); + if (rv < 0) { + PLOG(ERROR) << "Could not bind NETLINK socket"; + AbortAndForceOnline(); + return; + } } // Request dump of addresses. @@ -186,38 +203,45 @@ void AddressTrackerLinux::Init() { // Consume pending message to populate links_online_, but don't notify. ReadMessages(&address_changed, &link_changed, &tunnel_changed); { - base::AutoLock lock(is_offline_lock_); + AddressTrackerAutoLock lock(*this, is_offline_lock_); is_offline_initialized_ = true; is_offline_initialized_cv_.Signal(); } - rv = base::MessageLoopForIO::current()->WatchFileDescriptor( - netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); - if (rv < 0) { - PLOG(ERROR) << "Could not watch NETLINK socket"; - AbortAndForceOnline(); - return; + if (tracking_) { + rv = base::MessageLoopForIO::current()->WatchFileDescriptor( + netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); + if (rv < 0) { + PLOG(ERROR) << "Could not watch NETLINK socket"; + AbortAndForceOnline(); + return; + } } } void AddressTrackerLinux::AbortAndForceOnline() { CloseSocket(); - base::AutoLock lock(is_offline_lock_); + AddressTrackerAutoLock lock(*this, is_offline_lock_); is_offline_ = false; is_offline_initialized_ = true; is_offline_initialized_cv_.Signal(); } AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const { - base::AutoLock lock(address_map_lock_); + AddressTrackerAutoLock lock(*this, address_map_lock_); return address_map_; } +base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const { + AddressTrackerAutoLock lock(*this, online_links_lock_); + return online_links_; +} + NetworkChangeNotifier::ConnectionType AddressTrackerLinux::GetCurrentConnectionType() { // http://crbug.com/125097 base::ThreadRestrictions::ScopedAllowWait allow_wait; - base::AutoLock lock(is_offline_lock_); + AddressTrackerAutoLock lock(*this, is_offline_lock_); // Make sure the initial offline state is set before returning. while (!is_offline_initialized_) { is_offline_initialized_cv_.Wait(); @@ -254,10 +278,15 @@ void AddressTrackerLinux::ReadMessages(bool* address_changed, return; } HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed); - }; + } if (*link_changed) { - base::AutoLock lock(is_offline_lock_); - is_offline_ = online_links_.empty(); + bool is_offline; + { + AddressTrackerAutoLock lock(*this, online_links_lock_); + is_offline = online_links_.empty(); + } + AddressTrackerAutoLock lock(*this, is_offline_lock_); + is_offline_ = is_offline; } } @@ -282,7 +311,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer, IPAddressNumber address; bool really_deprecated; if (GetAddress(header, &address, &really_deprecated)) { - base::AutoLock lock(address_map_lock_); + AddressTrackerAutoLock lock(*this, address_map_lock_); struct ifaddrmsg* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); // Routers may frequently (every few seconds) output the IPv6 ULA @@ -309,7 +338,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer, case RTM_DELADDR: { IPAddressNumber address; if (GetAddress(header, &address, NULL)) { - base::AutoLock lock(address_map_lock_); + AddressTrackerAutoLock lock(*this, address_map_lock_); if (address_map_.erase(address)) *address_changed = true; } @@ -319,12 +348,14 @@ void AddressTrackerLinux::HandleMessage(char* buffer, reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) && (msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) { + AddressTrackerAutoLock lock(*this, online_links_lock_); if (online_links_.insert(msg->ifi_index).second) { *link_changed = true; if (IsTunnelInterface(msg)) *tunnel_changed = true; } } else { + AddressTrackerAutoLock lock(*this, online_links_lock_); if (online_links_.erase(msg->ifi_index)) { *link_changed = true; if (IsTunnelInterface(msg)) @@ -335,6 +366,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer, case RTM_DELLINK: { const struct ifinfomsg* msg = reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); + AddressTrackerAutoLock lock(*this, online_links_lock_); if (online_links_.erase(msg->ifi_index)) { *link_changed = true; if (IsTunnelInterface(msg)) @@ -374,5 +406,23 @@ bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const { return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0; } +AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock( + const AddressTrackerLinux& tracker, + base::Lock& lock) + : tracker_(tracker), lock_(lock) { + if (tracker_.tracking_) { + lock_.Acquire(); + } else { + DCHECK(tracker_.thread_checker_.CalledOnValidThread()); + } +} + +AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() { + if (tracker_.tracking_) { + lock_.AssertAcquired(); + lock_.Release(); + } +} + } // namespace internal } // namespace net diff --git a/chromium/net/base/address_tracker_linux.h b/chromium/net/base/address_tracker_linux.h index 415e8c89e9d..a960287d4ad 100644 --- a/chromium/net/base/address_tracker_linux.h +++ b/chromium/net/base/address_tracker_linux.h @@ -20,6 +20,7 @@ #include "base/message_loop/message_loop.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "net/base/net_util.h" #include "net/base/network_change_notifier.h" @@ -33,20 +34,33 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : public: typedef std::map<IPAddressNumber, struct ifaddrmsg> AddressMap; - // Will run |address_callback| when the AddressMap changes, |link_callback| - // when the list of online links changes, and |tunnel_callback| when the list - // of online tunnels changes. + // Non-tracking version constructor: it takes a snapshot of the + // current system configuration. Once Init() returns, the + // configuration is available through GetOnlineLinks() and + // GetAddressMap(). + AddressTrackerLinux(); + + // Tracking version constructor: it will run |address_callback| when + // the AddressMap changes, |link_callback| when the list of online + // links changes, and |tunnel_callback| when the list of online + // tunnels changes. AddressTrackerLinux(const base::Closure& address_callback, const base::Closure& link_callback, const base::Closure& tunnel_callback); - virtual ~AddressTrackerLinux(); + ~AddressTrackerLinux() override; - // Starts watching system configuration for changes. The current thread must - // have a MessageLoopForIO. + // In tracking mode, it starts watching the system configuration for + // changes. The current thread must have a MessageLoopForIO. In + // non-tracking mode, once Init() returns, a snapshot of the system + // configuration is available through GetOnlineLinks() and + // GetAddressMap(). void Init(); AddressMap GetAddressMap() const; + // Returns set of interface indicies for online interfaces. + base::hash_set<int> GetOnlineLinks() const; + // Implementation of NetworkChangeNotifierLinux::GetCurrentConnectionType(). // Safe to call from any thread, but will block until Init() has completed. NetworkChangeNotifier::ConnectionType GetCurrentConnectionType(); @@ -54,6 +68,20 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : private: friend class AddressTrackerLinuxTest; + // In tracking mode, holds |lock| while alive. In non-tracking mode, + // enforces single-threaded access. + class AddressTrackerAutoLock { + public: + AddressTrackerAutoLock(const AddressTrackerLinux& tracker, + base::Lock& lock); + ~AddressTrackerAutoLock(); + + private: + const AddressTrackerLinux& tracker_; + base::Lock& lock_; + DISALLOW_COPY_AND_ASSIGN(AddressTrackerAutoLock); + }; + // A function that returns the name of an interface given the interface index // in |interface_index|. typedef const char* (*GetInterfaceNameFunction)(int interface_index); @@ -80,8 +108,8 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : void AbortAndForceOnline(); // MessageLoopForIO::Watcher: - virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE; + void OnFileCanReadWithoutBlocking(int fd) override; + void OnFileCanWriteWithoutBlocking(int /* fd */) override; // Close |netlink_fd_| void CloseSocket(); @@ -105,12 +133,17 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : AddressMap address_map_; // Set of interface indices for links that are currently online. + mutable base::Lock online_links_lock_; base::hash_set<int> online_links_; base::Lock is_offline_lock_; bool is_offline_; bool is_offline_initialized_; base::ConditionVariable is_offline_initialized_cv_; + bool tracking_; + + // Used to verify single-threaded access in non-tracking mode. + base::ThreadChecker thread_checker_; }; } // namespace internal diff --git a/chromium/net/base/address_tracker_linux_unittest.cc b/chromium/net/base/address_tracker_linux_unittest.cc index 1223d04f2ef..641220731b7 100644 --- a/chromium/net/base/address_tracker_linux_unittest.cc +++ b/chromium/net/base/address_tracker_linux_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_ptr.h" #include "net/base/address_tracker_linux.h" #include <linux/if.h> @@ -33,12 +34,18 @@ typedef std::vector<char> Buffer; class AddressTrackerLinuxTest : public testing::Test { protected: - AddressTrackerLinuxTest() - : tracker_(base::Bind(&base::DoNothing), - base::Bind(&base::DoNothing), - base::Bind(&base::DoNothing)), - original_get_interface_name_(tracker_.get_interface_name_) { - tracker_.get_interface_name_ = TestGetInterfaceName; + AddressTrackerLinuxTest() {} + + void InitializeAddressTracker(bool tracking) { + if (tracking) { + tracker_.reset(new AddressTrackerLinux(base::Bind(&base::DoNothing), + base::Bind(&base::DoNothing), + base::Bind(&base::DoNothing))); + } else { + tracker_.reset(new AddressTrackerLinux()); + } + original_get_interface_name_ = tracker_->get_interface_name_; + tracker_->get_interface_name_ = TestGetInterfaceName; } bool HandleAddressMessage(const Buffer& buf) { @@ -46,7 +53,7 @@ class AddressTrackerLinuxTest : public testing::Test { bool address_changed = false; bool link_changed = false; bool tunnel_changed = false; - tracker_.HandleMessage(&writable_buf[0], buf.size(), + tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed, &link_changed, &tunnel_changed); EXPECT_FALSE(link_changed); return address_changed; @@ -57,7 +64,7 @@ class AddressTrackerLinuxTest : public testing::Test { bool address_changed = false; bool link_changed = false; bool tunnel_changed = false; - tracker_.HandleMessage(&writable_buf[0], buf.size(), + tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed, &link_changed, &tunnel_changed); EXPECT_FALSE(address_changed); return link_changed; @@ -68,21 +75,21 @@ class AddressTrackerLinuxTest : public testing::Test { bool address_changed = false; bool link_changed = false; bool tunnel_changed = false; - tracker_.HandleMessage(&writable_buf[0], buf.size(), + tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed, &link_changed, &tunnel_changed); EXPECT_FALSE(address_changed); return tunnel_changed; } AddressTrackerLinux::AddressMap GetAddressMap() { - return tracker_.GetAddressMap(); + return tracker_->GetAddressMap(); } - const base::hash_set<int>* GetOnlineLinks() const { - return &tracker_.online_links_; + const base::hash_set<int> GetOnlineLinks() const { + return tracker_->GetOnlineLinks(); } - AddressTrackerLinux tracker_; + scoped_ptr<AddressTrackerLinux> tracker_; AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_; }; @@ -190,6 +197,8 @@ const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; TEST_F(AddressTrackerLinuxTest, NewAddress) { + InitializeAddressTracker(true); + const IPAddressNumber kEmpty; const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); @@ -224,6 +233,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddress) { } TEST_F(AddressTrackerLinuxTest, NewAddressChange) { + InitializeAddressTracker(true); + const IPAddressNumber kEmpty; const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); @@ -258,6 +269,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddressChange) { } TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { + InitializeAddressTracker(true); + const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); Buffer buffer; @@ -276,6 +289,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { } TEST_F(AddressTrackerLinuxTest, DeleteAddress) { + InitializeAddressTracker(true); + const IPAddressNumber kEmpty; const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); @@ -311,6 +326,8 @@ TEST_F(AddressTrackerLinuxTest, DeleteAddress) { } TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { + InitializeAddressTracker(true); + const IPAddressNumber kEmpty; const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); @@ -351,6 +368,8 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { } TEST_F(AddressTrackerLinuxTest, IgnoredMessage) { + InitializeAddressTracker(true); + const IPAddressNumber kEmpty; const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); @@ -381,6 +400,8 @@ TEST_F(AddressTrackerLinuxTest, IgnoredMessage) { } TEST_F(AddressTrackerLinuxTest, AddInterface) { + InitializeAddressTracker(true); + Buffer buffer; // Ignores loopback. @@ -388,69 +409,73 @@ TEST_F(AddressTrackerLinuxTest, AddInterface) { IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores not IFF_LOWER_UP. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores deletion. MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Verify success. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks()->count(0)); - EXPECT_EQ(1u, GetOnlineLinks()->size()); + EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().size()); // Ignores redundant enables. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks()->count(0)); - EXPECT_EQ(1u, GetOnlineLinks()->size()); + EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().size()); // Verify adding another online device (e.g. VPN) is considered a change. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks()->count(0)); - EXPECT_EQ(1u, GetOnlineLinks()->count(1)); - EXPECT_EQ(2u, GetOnlineLinks()->size()); + EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().count(1)); + EXPECT_EQ(2u, GetOnlineLinks().size()); } TEST_F(AddressTrackerLinuxTest, RemoveInterface) { + InitializeAddressTracker(true); + Buffer buffer; // Should disappear when not IFF_LOWER_UP. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_FALSE(GetOnlineLinks()->empty()); + EXPECT_FALSE(GetOnlineLinks().empty()); MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores redundant disables. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores deleting down interfaces. MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, 0, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); // Should disappear when deleted. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_FALSE(GetOnlineLinks()->empty()); + EXPECT_FALSE(GetOnlineLinks().empty()); MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_TRUE(GetOnlineLinks()->empty()); + EXPECT_TRUE(GetOnlineLinks().empty()); } TEST_F(AddressTrackerLinuxTest, TunnelInterface) { + InitializeAddressTracker(true); + Buffer buffer; // Ignores without "tun" prefixed name. @@ -493,10 +518,38 @@ TEST_F(AddressTrackerLinuxTest, TunnelInterface) { // Check AddressTrackerLinux::get_interface_name_ original implementation // doesn't crash or return NULL. TEST_F(AddressTrackerLinuxTest, GetInterfaceName) { + InitializeAddressTracker(true); + for (int i = 0; i < 10; i++) EXPECT_NE((const char*)NULL, original_get_interface_name_(i)); } +TEST_F(AddressTrackerLinuxTest, NonTrackingMode) { + InitializeAddressTracker(false); + + const IPAddressNumber kEmpty; + const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); + + Buffer buffer; + MakeAddrMessage( + RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, &buffer); + EXPECT_TRUE(HandleAddressMessage(buffer)); + AddressTrackerLinux::AddressMap map = GetAddressMap(); + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(kAddr0)); + EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); + + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + EXPECT_TRUE(HandleLinkMessage(buffer)); + EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().size()); +} + +TEST_F(AddressTrackerLinuxTest, NonTrackingModeInit) { + AddressTrackerLinux tracker; + tracker.Init(); +} + } // namespace } // namespace internal diff --git a/chromium/net/base/backoff_entry_unittest.cc b/chromium/net/base/backoff_entry_unittest.cc index 560b2133db1..89ec2c4d2f1 100644 --- a/chromium/net/base/backoff_entry_unittest.cc +++ b/chromium/net/base/backoff_entry_unittest.cc @@ -23,11 +23,9 @@ class TestBackoffEntry : public BackoffEntry { SetCustomReleaseTime(TimeTicks()); } - virtual ~TestBackoffEntry() {} + ~TestBackoffEntry() override {} - virtual TimeTicks ImplGetTimeNow() const OVERRIDE { - return now_; - } + TimeTicks ImplGetTimeNow() const override { return now_; } void set_now(const TimeTicks& now) { now_ = now; diff --git a/chromium/net/base/capturing_net_log.h b/chromium/net/base/capturing_net_log.h index 06bc976eeaa..5977533525e 100644 --- a/chromium/net/base/capturing_net_log.h +++ b/chromium/net/base/capturing_net_log.h @@ -72,7 +72,7 @@ class CapturingNetLog : public NetLog { typedef std::vector<CapturedEntry> CapturedEntryList; CapturingNetLog(); - virtual ~CapturingNetLog(); + ~CapturingNetLog() override; void SetLogLevel(LogLevel log_level); @@ -89,7 +89,7 @@ class CapturingNetLog : public NetLog { class Observer : public NetLog::ThreadSafeObserver { public: Observer(); - virtual ~Observer(); + ~Observer() override; // Returns the list of all entries in the log. void GetEntries(CapturedEntryList* entry_list) const; @@ -105,7 +105,7 @@ class CapturingNetLog : public NetLog { private: // ThreadSafeObserver implementation: - virtual void OnAddEntry(const Entry& entry) OVERRIDE; + void OnAddEntry(const Entry& entry) override; // Needs to be "mutable" so can use it in GetEntries(). mutable base::Lock lock_; diff --git a/chromium/net/base/chunked_upload_data_stream.cc b/chromium/net/base/chunked_upload_data_stream.cc new file mode 100644 index 00000000000..f1fbf0822c8 --- /dev/null +++ b/chromium/net/base/chunked_upload_data_stream.cc @@ -0,0 +1,103 @@ +// Copyright 2014 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 "net/base/chunked_upload_data_stream.h" + +#include "base/logging.h" +#include "base/stl_util.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" + +namespace net { + +ChunkedUploadDataStream::ChunkedUploadDataStream(int64 identifier) + : UploadDataStream(true, identifier), + read_index_(0), + read_offset_(0), + all_data_appended_(false), + read_buffer_len_(0) { +} + +ChunkedUploadDataStream::~ChunkedUploadDataStream() { +} + +void ChunkedUploadDataStream::AppendData( + const char* data, int data_len, bool is_done) { + DCHECK(!all_data_appended_); + DCHECK(data_len > 0 || is_done); + if (data_len > 0) { + DCHECK(data); + upload_data_.push_back(new std::vector<char>(data, data + data_len)); + } + all_data_appended_ = is_done; + + if (!read_buffer_.get()) + return; + + int result = ReadChunk(read_buffer_.get(), read_buffer_len_); + // Shouldn't get an error or ERR_IO_PENDING. + DCHECK_GE(result, 0); + read_buffer_ = NULL; + read_buffer_len_ = 0; + OnReadCompleted(result); +} + +int ChunkedUploadDataStream::InitInternal() { + // ResetInternal should already have been called. + DCHECK(!read_buffer_.get()); + DCHECK_EQ(0u, read_index_); + DCHECK_EQ(0u, read_offset_); + return OK; +} + +int ChunkedUploadDataStream::ReadInternal(IOBuffer* buf, int buf_len) { + DCHECK_LT(0, buf_len); + DCHECK(!read_buffer_.get()); + + int result = ReadChunk(buf, buf_len); + if (result == ERR_IO_PENDING) { + read_buffer_ = buf; + read_buffer_len_ = buf_len; + } + return result; +} + +void ChunkedUploadDataStream::ResetInternal() { + read_buffer_ = NULL; + read_buffer_len_ = 0; + read_index_ = 0; + read_offset_ = 0; +} + +int ChunkedUploadDataStream::ReadChunk(IOBuffer* buf, int buf_len) { + // Copy as much data as possible from |upload_data_| to |buf|. + int bytes_read = 0; + while (read_index_ < upload_data_.size() && bytes_read < buf_len) { + std::vector<char>* data = upload_data_[read_index_]; + size_t bytes_to_read = + std::min(static_cast<size_t>(buf_len - bytes_read), + data->size() - read_offset_); + memcpy(buf->data() + bytes_read, + vector_as_array(data) + read_offset_, + bytes_to_read); + bytes_read += bytes_to_read; + read_offset_ += bytes_to_read; + if (read_offset_ == data->size()) { + read_index_++; + read_offset_ = 0; + } + } + DCHECK_LE(bytes_read, buf_len); + + // If no data was written, and not all data has been appended, return + // ERR_IO_PENDING. The read will be completed in the next call to AppendData. + if (bytes_read == 0 && !all_data_appended_) + return ERR_IO_PENDING; + + if (read_index_ == upload_data_.size() && all_data_appended_) + SetIsFinalChunk(); + return bytes_read; +} + +} // namespace net diff --git a/chromium/net/base/chunked_upload_data_stream.h b/chromium/net/base/chunked_upload_data_stream.h new file mode 100644 index 00000000000..d17c8da3269 --- /dev/null +++ b/chromium/net/base/chunked_upload_data_stream.h @@ -0,0 +1,63 @@ +// Copyright 2014 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 NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ +#define NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_vector.h" +#include "net/base/completion_callback.h" +#include "net/base/net_export.h" +#include "net/base/upload_data_stream.h" + +namespace net { + +class IOBuffer; + +// Class with a push-based interface for uploading data. Buffers all data until +// the request is completed. Not recommended for uploading large amounts of +// seekable data, due to this buffering behavior. +class NET_EXPORT ChunkedUploadDataStream : public UploadDataStream { + public: + ChunkedUploadDataStream(int64 identifier); + + ~ChunkedUploadDataStream() override; + + // Adds data to the stream. |is_done| should be true if this is the last + // data to be appended. |data_len| must not be 0 unless |is_done| is true. + // Once called with |is_done| being true, must never be called again. + // TODO(mmenke): Consider using IOBuffers instead, to reduce data copies. + void AppendData(const char* data, int data_len, bool is_done); + + private: + // UploadDataStream implementation. + int InitInternal() override; + int ReadInternal(IOBuffer* buf, int buf_len) override; + void ResetInternal() override; + + int ReadChunk(IOBuffer* buf, int buf_len); + + // Index and offset of next element of |upload_data_| to be read. + size_t read_index_; + size_t read_offset_; + + // True once all data has been appended to the stream. + bool all_data_appended_; + + ScopedVector<std::vector<char>> upload_data_; + + // Buffer to write the next read's data to. Only set when a call to + // ReadInternal reads no data. + scoped_refptr<IOBuffer> read_buffer_; + int read_buffer_len_; + + DISALLOW_COPY_AND_ASSIGN(ChunkedUploadDataStream); +}; + +} // namespace net + +#endif // NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ diff --git a/chromium/net/base/chunked_upload_data_stream_unittest.cc b/chromium/net/base/chunked_upload_data_stream_unittest.cc new file mode 100644 index 00000000000..334e9a39428 --- /dev/null +++ b/chromium/net/base/chunked_upload_data_stream_unittest.cc @@ -0,0 +1,308 @@ +// Copyright 2014 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 "net/base/chunked_upload_data_stream.h" + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/base/upload_data_stream.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +const char kTestData[] = "0123456789"; +const size_t kTestDataSize = arraysize(kTestData) - 1; +const size_t kTestBufferSize = 1 << 14; // 16KB. + +} // namespace + +// Reads data once from the upload data stream, and returns the data as string. +// Expects the read to succeed synchronously. +std::string ReadSync(UploadDataStream* stream, int buffer_size) { + scoped_refptr<IOBuffer> buf = new IOBuffer(buffer_size); + int result = stream->Read(buf.get(), + buffer_size, + TestCompletionCallback().callback()); + EXPECT_GE(result, 0); + return std::string(buf->data(), result); +} + +// Check the case data is added after the first read attempt. +TEST(ChunkedUploadDataStreamTest, AppendOnce) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + stream.AppendData(kTestData, kTestDataSize, true); + int read = callback.WaitForResult(); + ASSERT_GE(read, 0); + EXPECT_EQ(kTestData, std::string(buf->data(), read)); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeRead) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + stream.AppendData(kTestData, kTestDataSize, true); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeInit) { + ChunkedUploadDataStream stream(0); + + stream.AppendData(kTestData, kTestDataSize, true); + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleAppends) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + for (size_t i = 0; i < kTestDataSize; ++i) { + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(i, stream.position()); + ASSERT_FALSE(stream.IsEOF()); + int bytes_read = stream.Read(buf.get(), + kTestBufferSize, + callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, bytes_read); + stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1); + ASSERT_EQ(1, callback.WaitForResult()); + EXPECT_EQ(kTestData[i], buf->data()[0]); + } + + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleAppendsBetweenReads) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + for (size_t i = 0; i < kTestDataSize; ++i) { + EXPECT_EQ(i, stream.position()); + ASSERT_FALSE(stream.IsEOF()); + stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1); + int bytes_read = stream.Read(buf.get(), + kTestBufferSize, + TestCompletionCallback().callback()); + ASSERT_EQ(1, bytes_read); + EXPECT_EQ(kTestData[i], buf->data()[0]); + } + + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +// Checks that multiple reads can be merged. +TEST(ChunkedUploadDataStreamTest, MultipleAppendsBeforeInit) { + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, 1, false); + stream.AppendData(kTestData + 1, 1, false); + stream.AppendData(kTestData + 2, kTestDataSize - 2, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleReads) { + // Use a read size different from the write size to test bounds checking. + const size_t kReadSize = kTestDataSize + 3; + + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kReadSize); + EXPECT_EQ("0123456789012", data); + EXPECT_EQ(kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("3456789012345", data); + EXPECT_EQ(2 * kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("6789012345678", data); + EXPECT_EQ(3 * kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("9", data); + EXPECT_EQ(4 * kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, EmptyUpload) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + stream.AppendData(NULL, 0, true); + int read = callback.WaitForResult(); + EXPECT_EQ(0, read); + EXPECT_EQ(0u, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, EmptyUploadEndedBeforeInit) { + ChunkedUploadDataStream stream(0); + stream.AppendData(NULL, 0, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + ASSERT_EQ("", data); + EXPECT_EQ(0u, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, RewindAfterComplete) { + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, 1, false); + stream.AppendData(kTestData + 1, kTestDataSize - 1, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); + + // Rewind stream and repeat. + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, RewindWhileReading) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + // Adding data now should not result in calling the original read callback, + // since the stream was re-initialized for reuse, which cancels all pending + // reads. + stream.AppendData(kTestData, kTestDataSize, true); + EXPECT_FALSE(callback.have_result()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); + EXPECT_FALSE(callback.have_result()); +} + +} // namespace net diff --git a/chromium/net/base/data_url.cc b/chromium/net/base/data_url.cc index 9699136c85f..58036c6a369 100644 --- a/chromium/net/base/data_url.cc +++ b/chromium/net/base/data_url.cc @@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "net/base/escape.h" #include "net/base/mime_util.h" +#include "net/http/http_util.h" #include "url/gurl.h" namespace net { @@ -42,7 +43,7 @@ bool DataURL::Parse(const GURL& url, std::string* mime_type, std::vector<std::string>::iterator iter = meta_data.begin(); if (iter != meta_data.end()) { mime_type->swap(*iter); - StringToLowerASCII(mime_type); + base::StringToLowerASCII(mime_type); ++iter; } @@ -57,14 +58,24 @@ bool DataURL::Parse(const GURL& url, std::string* mime_type, } else if (charset->empty() && iter->compare(0, kCharsetTagLength, kCharsetTag) == 0) { charset->assign(iter->substr(kCharsetTagLength)); + // The grammar for charset is not specially defined in RFC2045 and + // RFC2397. It just needs to be a token. + if (!net::HttpUtil::IsToken(*charset)) + return false; } } if (mime_type->empty()) { - // fallback to defaults if nothing specified in the URL: + // Fallback to the default if nothing specified in the mediatype part as + // specified in RFC2045. As specified in RFC2397, we use |charset| even if + // |mime_type| is empty. mime_type->assign("text/plain"); } else if (!ParseMimeTypeWithoutParameter(*mime_type, NULL, NULL)) { - return false; + // Fallback to the default as recommended in RFC2045 when the mediatype + // value is invalid. For this case, we don't respect |charset| but force it + // set to "US-ASCII". + mime_type->assign("text/plain"); + charset->assign("US-ASCII"); } if (charset->empty()) charset->assign("US-ASCII"); diff --git a/chromium/net/base/data_url.h b/chromium/net/base/data_url.h index 3c1e3033dc6..ee9c6d31dbf 100644 --- a/chromium/net/base/data_url.h +++ b/chromium/net/base/data_url.h @@ -35,8 +35,23 @@ class NET_EXPORT DataURL { // decoded data (e.g.., if the data URL specifies base64 encoding, then the // returned data is base64 decoded, and any %-escaped bytes are unescaped). // - // If the URL is malformed, then this method will return false, and its - // output variables will remain unchanged. On success, true is returned. + // If the media type value doesn't match the media-type production defined in + // RFC 7231, mime_type will be set to the default value "text/plain". We + // don't simply fail for this grammar violation since Chromium had been + // accepting such invalid values. For example, <img> element with the src + // attribute set to a data URL with an invalid media type "image" (without a + // slash and subtype) had been displayed. However, the value this method will + // store in mime_type argument can be used for generating other headers, etc. + // This could lead to security vulnerability. We don't want to accept + // arbitrary value and ask each caller to validate the return value. + // + // If the charset parameter is specified but its value doesn't match the + // token production defined in RFC 7230, this method simply fails and returns + // false. + // + // If there's any other grammar violation in the URL, then this method will + // return false. Output variables may be changed and contain invalid data. On + // success, true is returned. // // OPTIONAL: If |data| is NULL, then the <data> section will not be parsed // or validated. diff --git a/chromium/net/base/data_url_unittest.cc b/chromium/net/base/data_url_unittest.cc index 43f881f7084..bcb2b49ad6c 100644 --- a/chromium/net/base/data_url_unittest.cc +++ b/chromium/net/base/data_url_unittest.cc @@ -40,10 +40,10 @@ TEST(DataURLTest, Parse) { "" }, { "data:;charset=,test", - true, - "text/plain", - "US-ASCII", - "test" }, + false, + "", + "", + "" }, { "data:TeXt/HtMl,<b>x</b>", true, @@ -63,6 +63,28 @@ TEST(DataURLTest, Parse) { "US-ASCII", "hello world" }, + // Allow invalid mediatype for backward compatibility but set mime_type to + // "text/plain" instead of the invalid mediatype. + { "data:foo,boo", + true, + "text/plain", + "US-ASCII", + "boo" }, + + // When accepting an invalid mediatype, override charset with "US-ASCII" + { "data:foo;charset=UTF-8,boo", + true, + "text/plain", + "US-ASCII", + "boo" }, + + // Invalid mediatype. Includes a slash but the type part is not a token. + { "data:f(oo/bar;baz=1;charset=kk,boo", + true, + "text/plain", + "US-ASCII", + "boo" }, + { "data:foo/bar;baz=1;charset=kk,boo", true, "foo/bar", @@ -88,13 +110,6 @@ TEST(DataURLTest, Parse) { "US-ASCII", "<html><body><b>hello world</b></body></html>" }, - // Bad mime type - { "data:f(oo/bar;baz=1;charset=kk,boo", - false, - "", - "", - "" }, - // the comma cannot be url-escaped! { "data:%2Cblah", false, @@ -169,6 +184,44 @@ TEST(DataURLTest, Parse) { "", "" }, + // BiDi control characters should be unescaped and preserved as is, and + // should not be replaced with % versions. In the below case, \xE2\x80\x8F + // is the RTL mark and the parsed text should preserve it as is. + { + "data:text/plain;charset=utf-8,\xE2\x80\x8Ftest", + true, + "text/plain", + "utf-8", + "\xE2\x80\x8Ftest"}, + + // Same as above but with Arabic text after RTL mark. + { + "data:text/plain;charset=utf-8," + "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1", + true, + "text/plain", + "utf-8", + "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1"}, + + // RTL mark encoded as %E2%80%8F should be unescaped too. Note that when + // wrapped in a GURL, this URL and the next effectively become the same as + // the previous two URLs. + { + "data:text/plain;charset=utf-8,%E2%80%8Ftest", + true, + "text/plain", + "utf-8", + "\xE2\x80\x8Ftest"}, + + // Same as above but with Arabic text after RTL mark. + { + "data:text/plain;charset=utf-8," + "%E2%80%8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1", + true, + "text/plain", + "utf-8", + "\xE2\x80\x8F\xD8\xA7\xD8\xAE\xD8\xAA\xD8\xA8\xD8\xA7\xD8\xB1"} + // TODO(darin): add more interesting tests }; diff --git a/chromium/net/base/directory_lister.cc b/chromium/net/base/directory_lister.cc index e75e9f808dc..841f454c814 100644 --- a/chromium/net/base/directory_lister.cc +++ b/chromium/net/base/directory_lister.cc @@ -8,8 +8,8 @@ #include <vector> #include "base/bind.h" -#include "base/file_util.h" #include "base/files/file_enumerator.h" +#include "base/files/file_util.h" #include "base/i18n/file_util_icu.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread_restrictions.h" @@ -41,8 +41,8 @@ bool CompareAlphaDirsFirst(const DirectoryLister::DirectoryListerData& a, if (a_is_directory != b_is_directory) return a_is_directory; - return file_util::LocaleAwareCompareFilenames(a.info.GetName(), - b.info.GetName()); + return base::i18n::LocaleAwareCompareFilenames(a.info.GetName(), + b.info.GetName()); } bool CompareDate(const DirectoryLister::DirectoryListerData& a, @@ -66,7 +66,7 @@ bool CompareDate(const DirectoryLister::DirectoryListerData& a, // Static. bool CompareFullPath(const DirectoryLister::DirectoryListerData& a, const DirectoryLister::DirectoryListerData& b) { - return file_util::LocaleAwareCompareFilenames(a.path, b.path); + return base::i18n::LocaleAwareCompareFilenames(a.path, b.path); } void SortData(std::vector<DirectoryLister::DirectoryListerData>* data, diff --git a/chromium/net/base/directory_lister_unittest.cc b/chromium/net/base/directory_lister_unittest.cc index 005ce0d5128..869e4f688b9 100644 --- a/chromium/net/base/directory_lister_unittest.cc +++ b/chromium/net/base/directory_lister_unittest.cc @@ -5,8 +5,8 @@ #include <list> #include <utility> -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/i18n/file_util_icu.h" #include "base/message_loop/message_loop.h" @@ -27,15 +27,14 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { quit_loop_after_each_file_(quit_loop_after_each_file) { } - virtual void OnListFile( - const DirectoryLister::DirectoryListerData& data) OVERRIDE { + void OnListFile(const DirectoryLister::DirectoryListerData& data) override { file_list_.push_back(data.info); paths_.push_back(data.path); if (quit_loop_after_each_file_) base::MessageLoop::current()->Quit(); } - virtual void OnListDone(int error) OVERRIDE { + void OnListDone(int error) override { error_ = error; base::MessageLoop::current()->Quit(); if (recursive_) @@ -50,7 +49,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { for (size_t previous = 0, current = 1; current < file_list_.size(); previous++, current++) { - EXPECT_TRUE(file_util::LocaleAwareCompareFilenames( + EXPECT_TRUE(base::i18n::LocaleAwareCompareFilenames( paths_[previous], paths_[current])); } } @@ -71,7 +70,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { file_list_[current].GetName().BaseName().value()); EXPECT_EQ(file_list_[previous].IsDirectory(), file_list_[current].IsDirectory()); - EXPECT_TRUE(file_util::LocaleAwareCompareFilenames( + EXPECT_TRUE(base::i18n::LocaleAwareCompareFilenames( file_list_[previous].GetName(), file_list_[current].GetName())); } @@ -92,8 +91,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { class DirectoryListerTest : public PlatformTest { public: - - virtual void SetUp() OVERRIDE { + void SetUp() override { const int kMaxDepth = 3; const int kBranchingFactor = 4; const int kFilesPerDirectory = 5; diff --git a/chromium/net/base/dns_reloader.cc b/chromium/net/base/dns_reloader.cc index 04abcb18552..e0e0b76483a 100644 --- a/chromium/net/base/dns_reloader.cc +++ b/chromium/net/base/dns_reloader.cc @@ -46,7 +46,7 @@ class DnsReloader : public net::NetworkChangeNotifier::DNSObserver { }; // NetworkChangeNotifier::DNSObserver: - virtual void OnDNSChanged() OVERRIDE { + void OnDNSChanged() override { DCHECK(base::MessageLoopForIO::IsCurrent()); base::AutoLock l(lock_); resolver_generation_++; @@ -84,7 +84,7 @@ class DnsReloader : public net::NetworkChangeNotifier::DNSObserver { net::NetworkChangeNotifier::AddDNSObserver(this); } - virtual ~DnsReloader() { + ~DnsReloader() override { NOTREACHED(); // LeakyLazyInstance is not destructed. } @@ -110,7 +110,7 @@ base::LazyInstance<DnsReloader>::Leaky namespace net { void EnsureDnsReloaderInit() { - DnsReloader* t ALLOW_UNUSED = g_dns_reloader.Pointer(); + g_dns_reloader.Pointer(); } void DnsReloaderMaybeReload() { diff --git a/chromium/net/base/dns_util_unittest.cc b/chromium/net/base/dns_util_unittest.cc index d91753f4f73..06f1fb25877 100644 --- a/chromium/net/base/dns_util_unittest.cc +++ b/chromium/net/base/dns_util_unittest.cc @@ -31,15 +31,15 @@ TEST_F(DNSUtilTest, DNSDomainFromDot) { EXPECT_EQ(out, IncludeNUL("\003www\006google\003com")); // Label is 63 chars: still valid - EXPECT_TRUE(DNSDomainFromDot("123456789a123456789a123456789a123456789a123456789a123456789a123", &out)); - EXPECT_EQ(out, IncludeNUL("\077123456789a123456789a123456789a123456789a123456789a123456789a123")); + EXPECT_TRUE(DNSDomainFromDot("z23456789a123456789a123456789a123456789a123456789a123456789a123", &out)); + EXPECT_EQ(out, IncludeNUL("\077z23456789a123456789a123456789a123456789a123456789a123456789a123")); // Label is too long: invalid EXPECT_FALSE(DNSDomainFromDot("123456789a123456789a123456789a123456789a123456789a123456789a1234", &out)); // 253 characters in the name: still valid - EXPECT_TRUE(DNSDomainFromDot("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123", &out)); - EXPECT_EQ(out, IncludeNUL("\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\011123456789\003123")); + EXPECT_TRUE(DNSDomainFromDot("abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abc", &out)); + EXPECT_EQ(out, IncludeNUL("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi\003abc")); // 254 characters in the name: invalid EXPECT_FALSE(DNSDomainFromDot("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234", &out)); diff --git a/chromium/net/base/elements_upload_data_stream.cc b/chromium/net/base/elements_upload_data_stream.cc new file mode 100644 index 00000000000..86ea28c7213 --- /dev/null +++ b/chromium/net/base/elements_upload_data_stream.cc @@ -0,0 +1,166 @@ +// 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 "net/base/elements_upload_data_stream.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_element_reader.h" + +namespace net { + +ElementsUploadDataStream::ElementsUploadDataStream( + ScopedVector<UploadElementReader> element_readers, + int64 identifier) + : UploadDataStream(false, identifier), + element_readers_(element_readers.Pass()), + element_index_(0), + read_failed_(false), + weak_ptr_factory_(this) { +} + +ElementsUploadDataStream::~ElementsUploadDataStream() { +} + +scoped_ptr<UploadDataStream> ElementsUploadDataStream::CreateWithReader( + scoped_ptr<UploadElementReader> reader, + int64 identifier) { + ScopedVector<UploadElementReader> readers; + readers.push_back(reader.release()); + return scoped_ptr<UploadDataStream>( + new ElementsUploadDataStream(readers.Pass(), identifier)); +} + +int ElementsUploadDataStream::InitInternal() { + return InitElements(0); +} + +int ElementsUploadDataStream::ReadInternal( + IOBuffer* buf, + int buf_len) { + DCHECK_GT(buf_len, 0); + return ReadElements(new DrainableIOBuffer(buf, buf_len)); +} + +bool ElementsUploadDataStream::IsInMemory() const { + for (size_t i = 0; i < element_readers_.size(); ++i) { + if (!element_readers_[i]->IsInMemory()) + return false; + } + return true; +} + +const ScopedVector<UploadElementReader>* +ElementsUploadDataStream::GetElementReaders() const { + return &element_readers_; +} + +void ElementsUploadDataStream::ResetInternal() { + weak_ptr_factory_.InvalidateWeakPtrs(); + read_failed_ = false; + element_index_ = 0; +} + +int ElementsUploadDataStream::InitElements(size_t start_index) { + // Call Init() for all elements. + for (size_t i = start_index; i < element_readers_.size(); ++i) { + UploadElementReader* reader = element_readers_[i]; + // When new_result is ERR_IO_PENDING, InitInternal() will be called + // with start_index == i + 1 when reader->Init() finishes. + int result = reader->Init( + base::Bind(&ElementsUploadDataStream::OnInitElementCompleted, + weak_ptr_factory_.GetWeakPtr(), + i)); + DCHECK(result != ERR_IO_PENDING || !reader->IsInMemory()); + DCHECK_LE(result, OK); + if (result != OK) + return result; + } + + uint64 total_size = 0; + for (size_t i = 0; i < element_readers_.size(); ++i) { + total_size += element_readers_[i]->GetContentLength(); + } + SetSize(total_size); + return OK; +} + +void ElementsUploadDataStream::OnInitElementCompleted(size_t index, + int result) { + DCHECK_NE(ERR_IO_PENDING, result); + + // Check the last result. + if (result == OK) + result = InitElements(index + 1); + + if (result != ERR_IO_PENDING) + OnInitCompleted(result); +} + +int ElementsUploadDataStream::ReadElements( + const scoped_refptr<DrainableIOBuffer>& buf) { + while (!read_failed_ && element_index_ < element_readers_.size()) { + UploadElementReader* reader = element_readers_[element_index_]; + + if (reader->BytesRemaining() == 0) { + ++element_index_; + continue; + } + + if (buf->BytesRemaining() == 0) + break; + + int result = reader->Read( + buf.get(), + buf->BytesRemaining(), + base::Bind(&ElementsUploadDataStream::OnReadElementCompleted, + weak_ptr_factory_.GetWeakPtr(), + buf)); + if (result == ERR_IO_PENDING) + return ERR_IO_PENDING; + ProcessReadResult(buf, result); + } + + if (read_failed_) { + // If an error occured during read operation, then pad with zero. + // Otherwise the server will hang waiting for the rest of the data. + int num_bytes_to_fill = std::min( + static_cast<uint64>(buf->BytesRemaining()), + size() - position() - buf->BytesConsumed()); + DCHECK_LE(0, num_bytes_to_fill); + memset(buf->data(), 0, num_bytes_to_fill); + buf->DidConsume(num_bytes_to_fill); + } + + return buf->BytesConsumed(); +} + +void ElementsUploadDataStream::OnReadElementCompleted( + const scoped_refptr<DrainableIOBuffer>& buf, + int result) { + ProcessReadResult(buf, result); + + result = ReadElements(buf); + if (result != ERR_IO_PENDING) + OnReadCompleted(result); +} + +void ElementsUploadDataStream::ProcessReadResult( + const scoped_refptr<DrainableIOBuffer>& buf, + int result) { + DCHECK_NE(ERR_IO_PENDING, result); + DCHECK(!read_failed_); + + if (result >= 0) { + buf->DidConsume(result); + } else { + read_failed_ = true; + } +} + +} // namespace net diff --git a/chromium/net/base/elements_upload_data_stream.h b/chromium/net/base/elements_upload_data_stream.h new file mode 100644 index 00000000000..5101114a3cc --- /dev/null +++ b/chromium/net/base/elements_upload_data_stream.h @@ -0,0 +1,85 @@ +// 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 NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ +#define NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ + +#include "base/basictypes.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "net/base/net_export.h" +#include "net/base/upload_data_stream.h" + +namespace net { + +class DrainableIOBuffer; +class IOBuffer; +class UploadElementReader; + +// A non-chunked UploadDataStream consisting of one or more UploadElements. +class NET_EXPORT ElementsUploadDataStream : public UploadDataStream { + public: + ElementsUploadDataStream(ScopedVector<UploadElementReader> element_readers, + int64 identifier); + + ~ElementsUploadDataStream() override; + + // Creates an ElementsUploadDataStream with a single reader. Returns a + // scoped_ptr<UploadDataStream> for ease of use. + static scoped_ptr<UploadDataStream> CreateWithReader( + scoped_ptr<UploadElementReader> reader, + int64 identifier); + + private: + // UploadDataStream implementation. + bool IsInMemory() const override; + const ScopedVector<UploadElementReader>* GetElementReaders() const override; + int InitInternal() override; + int ReadInternal(IOBuffer* buf, int buf_len) override; + void ResetInternal() override; + + // Runs Init() for all element readers. + // This method is used to implement InitInternal(). + int InitElements(size_t start_index); + + // Called when the |index| element finishes initialization. If it succeeded, + // continues with the |index + 1| element. Calls OnInitCompleted on error or + // when all elements have been initialized. + void OnInitElementCompleted(size_t index, int result); + + // Reads data from the element readers. + // This method is used to implement Read(). + int ReadElements(const scoped_refptr<DrainableIOBuffer>& buf); + + // Resumes pending read and calls OnReadCompleted with a result when + // necessary. + void OnReadElementCompleted(const scoped_refptr<DrainableIOBuffer>& buf, + int result); + + // Processes result of UploadElementReader::Read(). If |result| indicates + // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. + void ProcessReadResult(const scoped_refptr<DrainableIOBuffer>& buf, + int result); + + ScopedVector<UploadElementReader> element_readers_; + + // Index of the current upload element (i.e. the element currently being + // read). The index is used as a cursor to iterate over elements in + // |upload_data_|. + size_t element_index_; + + // True if an error occcured during read operation. + bool read_failed_; + + base::WeakPtrFactory<ElementsUploadDataStream> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ElementsUploadDataStream); +}; + +} // namespace net + +#endif // NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ diff --git a/chromium/net/base/upload_data_stream_unittest.cc b/chromium/net/base/elements_upload_data_stream_unittest.cc index 90a78d24b52..1882e9a9224 100644 --- a/chromium/net/base/upload_data_stream_unittest.cc +++ b/chromium/net/base/elements_upload_data_stream_unittest.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/base/upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include <algorithm> #include <vector> #include "base/basictypes.h" #include "base/bind.h" -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" @@ -20,6 +20,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -67,9 +68,9 @@ class MockUploadElementReader : public UploadElementReader { // UploadElementReader overrides. MOCK_METHOD1(Init, int(const CompletionCallback& callback)); - virtual uint64 GetContentLength() const OVERRIDE { return content_length_; } - virtual uint64 BytesRemaining() const OVERRIDE { return bytes_remaining_; } - virtual bool IsInMemory() const OVERRIDE { return is_in_memory_; } + virtual uint64 GetContentLength() const override { return content_length_; } + virtual uint64 BytesRemaining() const override { return bytes_remaining_; } + virtual bool IsInMemory() const override { return is_in_memory_; } MOCK_METHOD3(Read, int(IOBuffer* buf, int buf_length, const CompletionCallback& callback)); @@ -122,13 +123,13 @@ class MockUploadElementReader : public UploadElementReader { } // namespace -class UploadDataStreamTest : public PlatformTest { +class ElementsUploadDataStreamTest : public PlatformTest { public: - virtual void SetUp() { + void SetUp() override { PlatformTest::SetUp(); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } - virtual ~UploadDataStreamTest() { + ~ElementsUploadDataStreamTest() override { element_readers_.clear(); base::RunLoop().RunUntilIdle(); } @@ -141,35 +142,37 @@ class UploadDataStreamTest : public PlatformTest { ScopedVector<UploadElementReader> element_readers_; }; -TEST_F(UploadDataStreamTest, EmptyUploadData) { - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(0U, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_TRUE(stream.IsEOF()); +TEST_F(ElementsUploadDataStreamTest, EmptyUploadData) { + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(0U, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, ConsumeAllBytes) { +TEST_F(ElementsUploadDataStreamTest, ConsumeAllBytes) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { int bytes_read = - stream.Read(buf.get(), kTestBufferSize, CompletionCallback()); + stream->Read(buf.get(), kTestBufferSize, CompletionCallback()); ASSERT_LE(0, bytes_read); // Not an error. } - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, File) { +TEST_F(ElementsUploadDataStreamTest, File) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -184,26 +187,27 @@ TEST_F(UploadDataStreamTest, File) { base::Time())); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); ASSERT_LE(0, read_callback.WaitForResult()); // Not an error. } - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, FileSmallerThanLength) { +TEST_F(ElementsUploadDataStreamTest, FileSmallerThanLength) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -222,32 +226,33 @@ TEST_F(UploadDataStreamTest, FileSmallerThanLength) { base::Time())); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kFakeSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kFakeSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); uint64 read_counter = 0; scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); int bytes_read = read_callback.WaitForResult(); ASSERT_LE(0, bytes_read); // Not an error. read_counter += bytes_read; - EXPECT_EQ(read_counter, stream.position()); + EXPECT_EQ(read_counter, stream->position()); } // UpdateDataStream will pad out the file with 0 bytes so that the HTTP // transaction doesn't hang. Therefore we expected the full size. EXPECT_EQ(kFakeSize, read_counter); - EXPECT_EQ(read_counter, stream.position()); + EXPECT_EQ(read_counter, stream->position()); } -TEST_F(UploadDataStreamTest, ReadErrorSync) { +TEST_F(ElementsUploadDataStreamTest, ReadErrorSync) { // This element cannot be read. MockUploadElementReader* reader = new MockUploadElementReader(kTestDataSize, true); @@ -259,13 +264,14 @@ TEST_F(UploadDataStreamTest, ReadErrorSync) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_EQ(kTestDataSize*2, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_EQ(kTestDataSize*2, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); // Prepare a buffer filled with non-zero data. scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -273,16 +279,16 @@ TEST_F(UploadDataStreamTest, ReadErrorSync) { // Read() results in success even when the reader returns error. EXPECT_EQ(static_cast<int>(kTestDataSize * 2), - stream.Read(buf.get(), kTestBufferSize, CompletionCallback())); - EXPECT_EQ(kTestDataSize * 2, stream.position()); - EXPECT_TRUE(stream.IsEOF()); + stream->Read(buf.get(), kTestBufferSize, CompletionCallback())); + EXPECT_EQ(kTestDataSize * 2, stream->position()); + EXPECT_TRUE(stream->IsEOF()); // The buffer is filled with zero. EXPECT_EQ(static_cast<int>(kTestDataSize*2), std::count(buf->data(), buf->data() + kTestBufferSize, 0)); } -TEST_F(UploadDataStreamTest, ReadErrorAsync) { +TEST_F(ElementsUploadDataStreamTest, ReadErrorAsync) { // This element cannot be read. MockUploadElementReader* reader = new MockUploadElementReader(kTestDataSize, false); @@ -294,15 +300,16 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback init_callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); EXPECT_EQ(OK, init_callback.WaitForResult()); - EXPECT_EQ(kTestDataSize*2, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); // Prepare a buffer filled with non-zero data. scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -311,17 +318,17 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) { // Read() results in success even when the reader returns error. TestCompletionCallback read_callback; ASSERT_EQ(ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize * 2), read_callback.WaitForResult()); - EXPECT_EQ(kTestDataSize*2, stream.position()); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->position()); + EXPECT_TRUE(stream->IsEOF()); // The buffer is filled with zero. EXPECT_EQ(static_cast<int>(kTestDataSize*2), std::count(buf->data(), buf->data() + kTestBufferSize, 0)); } -TEST_F(UploadDataStreamTest, FileAndBytes) { +TEST_F(ElementsUploadDataStreamTest, FileAndBytes) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -342,49 +349,29 @@ TEST_F(UploadDataStreamTest, FileAndBytes) { const uint64 kStreamSize = kTestDataSize + kFileRangeLength; TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kStreamSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kStreamSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; const int result = - stream.Read(buf.get(), kTestBufferSize, read_callback.callback()); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback()); const int bytes_read = result != ERR_IO_PENDING ? result : read_callback.WaitForResult(); ASSERT_LE(0, bytes_read); // Not an error. } - EXPECT_EQ(kStreamSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); -} - -TEST_F(UploadDataStreamTest, Chunk) { - const uint64 kStreamSize = kTestDataSize*2; - UploadDataStream stream(UploadDataStream::CHUNKED, 0); - stream.AppendChunk(kTestData, kTestDataSize, false); - stream.AppendChunk(kTestData, kTestDataSize, true); - - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(0U, stream.size()); // Content-Length is 0 for chunked data. - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); - scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { - int bytes_read = - stream.Read(buf.get(), kTestBufferSize, CompletionCallback()); - ASSERT_LE(0, bytes_read); // Not an error. - } - EXPECT_EQ(kStreamSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kStreamSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } // Init() with on-memory and not-on-memory readers. -TEST_F(UploadDataStreamTest, InitAsync) { +TEST_F(ElementsUploadDataStreamTest, InitAsync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -408,16 +395,17 @@ TEST_F(UploadDataStreamTest, InitAsync) { EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(OK, callback.WaitForResult()); } // Init() of a reader fails asynchronously. -TEST_F(UploadDataStreamTest, InitAsyncFailureAsync) { +TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureAsync) { // Create UploadDataStream with a mock reader. MockUploadElementReader* reader = NULL; @@ -425,16 +413,17 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureAsync) { reader->SetAsyncInitExpectation(ERR_FAILED); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(ERR_FAILED, callback.WaitForResult()); } // Init() of a reader fails synchronously. -TEST_F(UploadDataStreamTest, InitAsyncFailureSync) { +TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureSync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -446,34 +435,36 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureSync) { EXPECT_CALL(*reader, Init(_)).WillOnce(Return(ERR_FAILED)); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(ERR_FAILED, callback.WaitForResult()); } // Read with a buffer whose size is same as the data. -TEST_F(UploadDataStreamTest, ReadAsyncWithExactSizeBuffer) { +TEST_F(ElementsUploadDataStreamTest, ReadAsyncWithExactSizeBuffer) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); - - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestDataSize); - int bytes_read = stream.Read(buf.get(), kTestDataSize, CompletionCallback()); + int bytes_read = stream->Read(buf.get(), kTestDataSize, CompletionCallback()); ASSERT_EQ(static_cast<int>(kTestDataSize), bytes_read); // Not an error. - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } // Async Read() with on-memory and not-on-memory readers. -TEST_F(UploadDataStreamTest, ReadAsync) { +TEST_F(ElementsUploadDataStreamTest, ReadAsync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -497,11 +488,12 @@ TEST_F(UploadDataStreamTest, ReadAsync) { reader->SetReadExpectation(kTestDataSize); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback init_callback; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); EXPECT_EQ(OK, init_callback.WaitForResult()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -509,28 +501,29 @@ TEST_F(UploadDataStreamTest, ReadAsync) { // Consume the first element. TestCompletionCallback read_callback1; EXPECT_EQ(static_cast<int>(kTestDataSize), - stream.Read(buf.get(), kTestDataSize, read_callback1.callback())); + stream->Read(buf.get(), kTestDataSize, read_callback1.callback())); base::MessageLoop::current()->RunUntilIdle(); EXPECT_FALSE(read_callback1.have_result()); // Consume the second element. TestCompletionCallback read_callback2; ASSERT_EQ(ERR_IO_PENDING, - stream.Read(buf.get(), kTestDataSize, read_callback2.callback())); + stream->Read(buf.get(), kTestDataSize, read_callback2.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize), read_callback2.WaitForResult()); // Consume the third and the fourth elements. TestCompletionCallback read_callback3; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestDataSize * 2, read_callback3.callback())); + stream->Read(buf.get(), kTestDataSize * 2, read_callback3.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize * 2), read_callback3.WaitForResult()); } -void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, - const base::Time& time, - bool error_expected) { +void ElementsUploadDataStreamTest::FileChangedHelper( + const base::FilePath& file_path, + const base::Time& time, + bool error_expected) { // Don't use element_readers_ here, as this function is called twice, and // reusing element_readers_ is wrong. ScopedVector<UploadElementReader> element_readers; @@ -538,8 +531,9 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, base::MessageLoopProxy::current().get(), file_path, 1, 2, time)); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); int error_code = init_callback.WaitForResult(); if (error_expected) ASSERT_EQ(ERR_UPLOAD_FILE_CHANGED, error_code); @@ -547,7 +541,7 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, ASSERT_EQ(OK, error_code); } -TEST_F(UploadDataStreamTest, FileChanged) { +TEST_F(ElementsUploadDataStreamTest, FileChanged) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -566,7 +560,7 @@ TEST_F(UploadDataStreamTest, FileChanged) { true); } -TEST_F(UploadDataStreamTest, MultipleInit) { +TEST_F(ElementsUploadDataStreamTest, MultipleInit) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -582,35 +576,36 @@ TEST_F(UploadDataStreamTest, MultipleInit) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); ASSERT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); // Call Init() again to reset. TestCompletionCallback init_callback2; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); ASSERT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read again. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, MultipleInitAsync) { +TEST_F(ElementsUploadDataStreamTest, MultipleInitAsync) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -627,33 +622,34 @@ TEST_F(UploadDataStreamTest, MultipleInitAsync) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; // Call Init(). - ASSERT_EQ(ERR_IO_PENDING, stream.Init(test_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(test_callback.callback())); EXPECT_EQ(OK, test_callback.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); // Call Init() again to reset. - ASSERT_EQ(ERR_IO_PENDING, stream.Init(test_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(test_callback.callback())); EXPECT_EQ(OK, test_callback.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read again. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, InitToReset) { +TEST_F(ElementsUploadDataStreamTest, InitToReset) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -669,7 +665,8 @@ TEST_F(UploadDataStreamTest, InitToReset) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -677,10 +674,10 @@ TEST_F(UploadDataStreamTest, InitToReset) { // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); EXPECT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read some. TestCompletionCallback read_callback1; @@ -688,29 +685,30 @@ TEST_F(UploadDataStreamTest, InitToReset) { scoped_refptr<IOBuffer> wrapped_buffer = new WrappedIOBuffer(&buf[0]); EXPECT_EQ( ERR_IO_PENDING, - stream.Read(wrapped_buffer.get(), buf.size(), read_callback1.callback())); + stream->Read(wrapped_buffer.get(), buf.size(), + read_callback1.callback())); EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult()); - EXPECT_EQ(buf.size(), stream.position()); + EXPECT_EQ(buf.size(), stream->position()); // Call Init to reset the state. TestCompletionCallback init_callback2; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); } -TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { +TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncInit) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -726,7 +724,8 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -734,31 +733,31 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { // Start Init. TestCompletionCallback init_callback1; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); // Call Init again to cancel the previous init. TestCompletionCallback init_callback2; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_TRUE(stream->IsEOF()); // Make sure callbacks are not called for cancelled operations. EXPECT_FALSE(init_callback1.have_result()); } -TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { +TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncRead) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -774,7 +773,8 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -782,10 +782,10 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); EXPECT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Start reading. TestCompletionCallback read_callback1; @@ -793,25 +793,26 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { scoped_refptr<IOBuffer> wrapped_buffer = new WrappedIOBuffer(&buf[0]); EXPECT_EQ( ERR_IO_PENDING, - stream.Read(wrapped_buffer.get(), buf.size(), read_callback1.callback())); + stream->Read(wrapped_buffer.get(), buf.size(), + read_callback1.callback())); // Call Init to cancel the previous read. TestCompletionCallback init_callback2; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_TRUE(stream->IsEOF()); // Make sure callbacks are not called for cancelled operations. EXPECT_FALSE(read_callback1.have_result()); diff --git a/chromium/net/base/escape.cc b/chromium/net/base/escape.cc index ab70f1db301..7a068f87ee5 100644 --- a/chromium/net/base/escape.cc +++ b/chromium/net/base/escape.cc @@ -39,15 +39,21 @@ struct Charmap { // Given text to escape and a Charmap defining which values to escape, // return an escaped string. If use_plus is true, spaces are converted // to +, otherwise, if spaces are in the charmap, they are converted to -// %20. -std::string Escape(const std::string& text, const Charmap& charmap, - bool use_plus) { +// %20. And if keep_escaped is true, %XX will be kept as it is, otherwise, if +// '%' is in the charmap, it is converted to %25. +std::string Escape(const std::string& text, + const Charmap& charmap, + bool use_plus, + bool keep_escaped = false) { std::string escaped; escaped.reserve(text.length() * 3); for (unsigned int i = 0; i < text.length(); ++i) { unsigned char c = static_cast<unsigned char>(text[i]); if (use_plus && ' ' == c) { escaped.push_back('+'); + } else if (keep_escaped && '%' == c && i + 2 < text.length() && + IsHexDigit(text[i + 1]) && IsHexDigit(text[i + 2])) { + escaped.push_back('%'); } else if (charmap.Contains(c)) { escaped.push_back('%'); escaped.push_back(IntToHex(c >> 4)); @@ -114,12 +120,50 @@ bool UnescapeUnsignedCharAtIndex(const STR& escaped_text, static_cast<typename STR::value_type>(escaped_text[index + 2])); if (IsHexDigit(most_sig_digit) && IsHexDigit(least_sig_digit)) { *value = HexDigitToInt(most_sig_digit) * 16 + - HexDigitToInt(least_sig_digit); + HexDigitToInt(least_sig_digit); return true; } return false; } +// Returns true if there is an Arabic Language Mark at |index|. |first_byte| +// is the byte at |index|. +template<typename STR> +bool HasArabicLanguageMarkAtIndex(const STR& escaped_text, + unsigned char first_byte, + size_t index) { + if (first_byte != 0xD8) + return false; + unsigned char second_byte; + if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 3, &second_byte)) + return false; + return second_byte == 0x9c; +} + +// Returns true if there is a BiDi control char at |index|. |first_byte| is the +// byte at |index|. +template<typename STR> +bool HasThreeByteBidiControlCharAtIndex(const STR& escaped_text, + unsigned char first_byte, + size_t index) { + if (first_byte != 0xE2) + return false; + unsigned char second_byte; + if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 3, &second_byte)) + return false; + if (second_byte != 0x80 && second_byte != 0x81) + return false; + unsigned char third_byte; + if (!UnescapeUnsignedCharAtIndex(escaped_text, index + 6, &third_byte)) + return false; + if (second_byte == 0x80) { + return third_byte == 0x8E || + third_byte == 0x8F || + (third_byte >= 0xAA && third_byte <= 0xAE); + } + return third_byte >= 0xA6 && third_byte <= 0xA9; +} + // Unescapes |escaped_text| according to |rules|, returning the resulting // string. Fills in an |adjustments| parameter, if non-NULL, so it reflects // the alterations done to the string that are not one-character-to-one- @@ -172,27 +216,21 @@ STR UnescapeURLWithAdjustmentsImpl( // U+2067 RIGHT-TO-LEFT ISOLATE (%E2%81%A7) // U+2068 FIRST STRONG ISOLATE (%E2%81%A8) // U+2069 POP DIRECTIONAL ISOLATE (%E2%81%A9) - - unsigned char second_byte; - // Check for ALM. - if ((first_byte == 0xD8) && - UnescapeUnsignedCharAtIndex(escaped_text, i + 3, &second_byte) && - (second_byte == 0x9c)) { - result.append(escaped_text, i, 6); - i += 5; - continue; - } - - // Check for other BiDi control characters. - if ((first_byte == 0xE2) && - UnescapeUnsignedCharAtIndex(escaped_text, i + 3, &second_byte) && - ((second_byte == 0x80) || (second_byte == 0x81))) { - unsigned char third_byte; - if (UnescapeUnsignedCharAtIndex(escaped_text, i + 6, &third_byte) && - ((second_byte == 0x80) ? - ((third_byte == 0x8E) || (third_byte == 0x8F) || - ((third_byte >= 0xAA) && (third_byte <= 0xAE))) : - ((third_byte >= 0xA6) && (third_byte <= 0xA9)))) { + // + // However, some schemes such as data: and file: need to parse the exact + // binary data when loading the URL. For that reason, CONTROL_CHARS allows + // unescaping BiDi control characters. + // DO NOT use CONTROL_CHARS if the parsed URL is going to be displayed + // in the UI. + if (!(rules & UnescapeRule::CONTROL_CHARS)) { + if (HasArabicLanguageMarkAtIndex(escaped_text, first_byte, i)) { + // Keep Arabic Language Mark escaped. + result.append(escaped_text, i, 6); + i += 5; + continue; + } + if (HasThreeByteBidiControlCharAtIndex(escaped_text, first_byte, i)) { + // Keep BiDi control char escaped. result.append(escaped_text, i, 9); i += 8; continue; @@ -244,7 +282,7 @@ void AppendEscapedCharForHTMLImpl(typename str::value_type c, str* output) { { '\'', "'" }, }; size_t k; - for (k = 0; k < ARRAYSIZE_UNSAFE(kCharsToEscape); ++k) { + for (k = 0; k < arraysize(kCharsToEscape); ++k) { if (c == kCharsToEscape[k].key) { const char* p = kCharsToEscape[k].replacement; while (*p) @@ -252,7 +290,7 @@ void AppendEscapedCharForHTMLImpl(typename str::value_type c, str* output) { break; } } - if (k == ARRAYSIZE_UNSAFE(kCharsToEscape)) + if (k == arraysize(kCharsToEscape)) output->push_back(c); } @@ -293,9 +331,9 @@ static const Charmap kNonASCIICharmap = {{ }}; // Everything except alphanumerics, the reserved characters(;/?:@&=+$,) and -// !'()*-._~% +// !'()*-._~#[] static const Charmap kExternalHandlerCharmap = {{ - 0xffffffffL, 0x5000080dL, 0x68000000L, 0xb8000001L, + 0xffffffffL, 0x50000025L, 0x50000000L, 0xb8000001L, 0xffffffffL, 0xffffffffL, 0xffffffffL, 0xffffffffL }}; @@ -318,7 +356,7 @@ std::string EscapeNonASCII(const std::string& input) { } std::string EscapeExternalHandlerValue(const std::string& text) { - return Escape(text, kExternalHandlerCharmap, false); + return Escape(text, kExternalHandlerCharmap, false, true); } void AppendEscapedCharForHTML(char c, std::string* output) { @@ -385,14 +423,14 @@ base::string16 UnescapeForHTML(const base::string16& input) { if (input.find(base::ASCIIToUTF16("&")) == std::string::npos) return input; - base::string16 ampersand_chars[ARRAYSIZE_UNSAFE(kEscapeToChars)]; + base::string16 ampersand_chars[arraysize(kEscapeToChars)]; base::string16 text(input); for (base::string16::iterator iter = text.begin(); iter != text.end(); ++iter) { if (*iter == '&') { // Potential ampersand encode char. size_t index = iter - text.begin(); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEscapeToChars); i++) { + for (size_t i = 0; i < arraysize(kEscapeToChars); i++) { if (ampersand_chars[i].empty()) { ampersand_chars[i] = base::ASCIIToUTF16(kEscapeToChars[i].ampersand_code); diff --git a/chromium/net/base/escape.h b/chromium/net/base/escape.h index 1915d244188..6c92333ba3d 100644 --- a/chromium/net/base/escape.h +++ b/chromium/net/base/escape.h @@ -42,8 +42,8 @@ NET_EXPORT std::string EscapeNonASCII(const std::string& input); // Escapes characters in text suitable for use as an external protocol handler // command. -// We %XX everything except alphanumerics and %-_.!~*'() and the restricted -// chracters (;/?:@&=+$,). +// We %XX everything except alphanumerics and -_.!~*'() and the restricted +// chracters (;/?:@&=+$,#[]) and a valid percent escape sequence (%XX). NET_EXPORT std::string EscapeExternalHandlerValue(const std::string& text); // Appends the given character to the output string, escaping the character if @@ -88,7 +88,10 @@ class UnescapeRule { // Unescapes control characters such as %01. This INCLUDES NULLs. This is // used for rare cases such as data: URL decoding where the result is binary - // data. You should not use this for normal URLs! + // data. This flag also unescapes BiDi control characters. + // + // DO NOT use CONTROL_CHARS if the URL is going to be displayed in the UI + // for security reasons. CONTROL_CHARS = 8, // URL queries use "+" for space. This flag controls that replacement. diff --git a/chromium/net/base/escape_unittest.cc b/chromium/net/base/escape_unittest.cc index 74ae29336d8..4d3bcbdd40c 100644 --- a/chromium/net/base/escape_unittest.cc +++ b/chromium/net/base/escape_unittest.cc @@ -232,7 +232,8 @@ TEST(EscapeTest, UnescapeURLComponent) { {L"Some%20random text %25%E2%80%84OK", UnescapeRule::NORMAL, L"Some%20random text %25\xE2\x80\x84OK"}, - // BiDi Control characters should not be unescaped. + // BiDi Control characters should not be unescaped unless explicity told to + // do so with UnescapeRule::CONTROL_CHARS {L"Some%20random text %25%D8%9COK", UnescapeRule::NORMAL, L"Some%20random text %25%D8%9COK"}, {L"Some%20random text %25%E2%80%8EOK", UnescapeRule::NORMAL, @@ -249,6 +250,31 @@ TEST(EscapeTest, UnescapeURLComponent) { L"Some%20random text %25%E2%81%A6OK"}, {L"Some%20random text %25%E2%81%A9OK", UnescapeRule::NORMAL, L"Some%20random text %25%E2%81%A9OK"}, + // UnescapeRule::CONTROL_CHARS should unescape BiDi Control characters. + {L"Some%20random text %25%D8%9COK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xD8\x9COK"}, + {L"Some%20random text %25%E2%80%8EOK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x80\x8EOK"}, + {L"Some%20random text %25%E2%80%8FOK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x80\x8FOK"}, + {L"Some%20random text %25%E2%80%AAOK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x80\xAAOK"}, + {L"Some%20random text %25%E2%80%ABOK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x80\xABOK"}, + {L"Some%20random text %25%E2%80%AEOK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x80\xAEOK"}, + {L"Some%20random text %25%E2%81%A6OK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x81\xA6OK"}, + {L"Some%20random text %25%E2%81%A9OK", + UnescapeRule::NORMAL | UnescapeRule::CONTROL_CHARS, + L"Some%20random text %25\xE2\x81\xA9OK"}, {L"Some%20random text %25%2dOK", UnescapeRule::SPACES, L"Some random text %25-OK"}, @@ -453,6 +479,43 @@ TEST(EscapeTest, UnescapeForHTML) { } } +TEST(EscapeTest, EscapeExternalHandlerValue) { + ASSERT_EQ( + // Escaped + "%02%0A%1D%20!%22#$%25&'()*+,-./0123456789:;" + "%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[%5C]%5E_%60abcdefghijklmnopqrstuvwxyz" + "%7B%7C%7D~%7F%80%FF", + // Most of the character space we care about, un-escaped + EscapeExternalHandlerValue( + "\x02\n\x1d !\"#$%&'()*+,-./0123456789:;" + "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz" + "{|}~\x7f\x80\xff")); + + ASSERT_EQ( + "!#$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_" + "abcdefghijklmnopqrstuvwxyz~", + EscapeExternalHandlerValue( + "!#$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_" + "abcdefghijklmnopqrstuvwxyz~")); + + ASSERT_EQ("%258k", EscapeExternalHandlerValue("%8k")); + ASSERT_EQ("a%25", EscapeExternalHandlerValue("a%")); + ASSERT_EQ("%25a", EscapeExternalHandlerValue("%a")); + ASSERT_EQ("a%258", EscapeExternalHandlerValue("a%8")); + ASSERT_EQ("%ab", EscapeExternalHandlerValue("%ab")); + ASSERT_EQ("%AB", EscapeExternalHandlerValue("%AB")); + + ASSERT_EQ("http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C", + EscapeExternalHandlerValue( + "http://example.com/path/sub?q=a|b|c&q=1|2|3#ref|")); + ASSERT_EQ("http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C", + EscapeExternalHandlerValue( + "http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C")); + ASSERT_EQ("http://[2001:db8:0:1]:80", + EscapeExternalHandlerValue("http://[2001:db8:0:1]:80")); +} } // namespace } // namespace net diff --git a/chromium/net/base/file_stream.cc b/chromium/net/base/file_stream.cc index bf56a49e8c0..cadbaed663e 100644 --- a/chromium/net/base/file_stream.cc +++ b/chromium/net/base/file_stream.cc @@ -30,12 +30,12 @@ int FileStream::Open(const base::FilePath& path, int open_flags, } DCHECK(open_flags & base::File::FLAG_ASYNC); - context_->OpenAsync(path, open_flags, callback); + context_->Open(path, open_flags, callback); return ERR_IO_PENDING; } int FileStream::Close(const CompletionCallback& callback) { - context_->CloseAsync(callback); + context_->Close(callback); return ERR_IO_PENDING; } @@ -43,13 +43,13 @@ bool FileStream::IsOpen() const { return context_->file().IsValid(); } -int FileStream::Seek(Whence whence, +int FileStream::Seek(base::File::Whence whence, int64 offset, const Int64CompletionCallback& callback) { if (!IsOpen()) return ERR_UNEXPECTED; - context_->SeekAsync(whence, offset, callback); + context_->Seek(whence, offset, callback); return ERR_IO_PENDING; } @@ -62,7 +62,7 @@ int FileStream::Read(IOBuffer* buf, // read(..., 0) will return 0, which indicates end-of-file. DCHECK_GT(buf_len, 0); - return context_->ReadAsync(buf, buf_len, callback); + return context_->Read(buf, buf_len, callback); } int FileStream::Write(IOBuffer* buf, @@ -71,17 +71,15 @@ int FileStream::Write(IOBuffer* buf, if (!IsOpen()) return ERR_UNEXPECTED; - // write(..., 0) will return 0, which indicates end-of-file. - DCHECK_GT(buf_len, 0); - - return context_->WriteAsync(buf, buf_len, callback); + DCHECK_GE(buf_len, 0); + return context_->Write(buf, buf_len, callback); } int FileStream::Flush(const CompletionCallback& callback) { if (!IsOpen()) return ERR_UNEXPECTED; - context_->FlushAsync(callback); + context_->Flush(callback); return ERR_IO_PENDING; } diff --git a/chromium/net/base/file_stream.h b/chromium/net/base/file_stream.h index 57011b77dec..89db65e15b5 100644 --- a/chromium/net/base/file_stream.h +++ b/chromium/net/base/file_stream.h @@ -12,7 +12,6 @@ #include "base/files/file.h" #include "net/base/completion_callback.h" -#include "net/base/file_stream_whence.h" #include "net/base/net_export.h" namespace base { @@ -69,7 +68,7 @@ class NET_EXPORT FileStream { // relative to the start of the file. Otherwise, an error code is returned. // It is invalid to request any asynchronous operations while there is an // in-flight asynchronous operation. - virtual int Seek(Whence whence, int64 offset, + virtual int Seek(base::File::Whence whence, int64 offset, const Int64CompletionCallback& callback); // Call this method to read data from the current stream position diff --git a/chromium/net/base/file_stream_context.cc b/chromium/net/base/file_stream_context.cc index fbfe5368dd8..8909b2ccefd 100644 --- a/chromium/net/base/file_stream_context.cc +++ b/chromium/net/base/file_stream_context.cc @@ -7,6 +7,7 @@ #include "base/files/file_path.h" #include "base/location.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/profiler/scoped_tracker.h" #include "base/task_runner.h" #include "base/task_runner_util.h" #include "base/threading/thread_restrictions.h" @@ -78,13 +79,15 @@ void FileStream::Context::Orphan() { if (!async_in_progress_) { CloseAndDelete(); } else if (file_.IsValid()) { +#if defined(OS_WIN) CancelIo(file_.GetPlatformFile()); +#endif } } -void FileStream::Context::OpenAsync(const base::FilePath& path, - int open_flags, - const CompletionCallback& callback) { +void FileStream::Context::Open(const base::FilePath& path, + int open_flags, + const CompletionCallback& callback) { DCHECK(!async_in_progress_); bool posted = base::PostTaskAndReplyWithResult( @@ -98,7 +101,7 @@ void FileStream::Context::OpenAsync(const base::FilePath& path, async_in_progress_ = true; } -void FileStream::Context::CloseAsync(const CompletionCallback& callback) { +void FileStream::Context::Close(const CompletionCallback& callback) { DCHECK(!async_in_progress_); bool posted = base::PostTaskAndReplyWithResult( task_runner_.get(), @@ -112,9 +115,9 @@ void FileStream::Context::CloseAsync(const CompletionCallback& callback) { async_in_progress_ = true; } -void FileStream::Context::SeekAsync(Whence whence, - int64 offset, - const Int64CompletionCallback& callback) { +void FileStream::Context::Seek(base::File::Whence whence, + int64 offset, + const Int64CompletionCallback& callback) { DCHECK(!async_in_progress_); bool posted = base::PostTaskAndReplyWithResult( @@ -130,7 +133,7 @@ void FileStream::Context::SeekAsync(Whence whence, async_in_progress_ = true; } -void FileStream::Context::FlushAsync(const CompletionCallback& callback) { +void FileStream::Context::Flush(const CompletionCallback& callback) { DCHECK(!async_in_progress_); bool posted = base::PostTaskAndReplyWithResult( @@ -147,6 +150,11 @@ void FileStream::Context::FlushAsync(const CompletionCallback& callback) { FileStream::Context::OpenResult FileStream::Context::OpenFileImpl( const base::FilePath& path, int open_flags) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 FileStream::Context::OpenFileImpl")); + #if defined(OS_POSIX) // Always use blocking IO. open_flags &= ~base::File::FLAG_ASYNC; @@ -172,7 +180,8 @@ FileStream::Context::OpenResult FileStream::Context::OpenFileImpl( } #endif // defined(OS_ANDROID) if (!file.IsValid()) - return OpenResult(base::File(), IOResult::FromOSError(GetLastErrno())); + return OpenResult(base::File(), + IOResult::FromOSError(logging::GetLastSystemErrorCode())); return OpenResult(file.Pass(), IOResult(OK, 0)); } @@ -182,11 +191,24 @@ FileStream::Context::IOResult FileStream::Context::CloseFileImpl() { return IOResult(OK, 0); } +FileStream::Context::IOResult FileStream::Context::FlushFileImpl() { + if (file_.Flush()) + return IOResult(OK, 0); + + return IOResult::FromOSError(logging::GetLastSystemErrorCode()); +} + void FileStream::Context::OnOpenCompleted(const CompletionCallback& callback, OpenResult open_result) { file_ = open_result.file.Pass(); - if (file_.IsValid() && !orphaned_) - OnAsyncFileOpened(); + if (file_.IsValid() && !orphaned_) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 FileStream::Context::OnOpenCompleted")); + + OnFileOpened(); + } OnAsyncCompleted(IntToInt64(callback), open_result.error_code); } @@ -214,7 +236,7 @@ void FileStream::Context::OnAsyncCompleted( const Int64CompletionCallback& callback, const IOResult& result) { // Reset this before Run() as Run() may issue a new async operation. Also it - // should be reset before CloseAsync() because it shouldn't run if any async + // should be reset before Close() because it shouldn't run if any async // operation is in progress. async_in_progress_ = false; if (orphaned_) diff --git a/chromium/net/base/file_stream_context.h b/chromium/net/base/file_stream_context.h index c4a06ee1de6..5493e251c66 100644 --- a/chromium/net/base/file_stream_context.h +++ b/chromium/net/base/file_stream_context.h @@ -33,7 +33,6 @@ #include "base/task_runner.h" #include "net/base/completion_callback.h" #include "net/base/file_stream.h" -#include "net/base/file_stream_whence.h" #if defined(OS_POSIX) #include <errno.h> @@ -66,17 +65,13 @@ class FileStream::Context { ~Context(); #endif - int ReadAsync(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback); + int Read(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback); - int WriteAsync(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback); - - //////////////////////////////////////////////////////////////////////////// - // Inline methods. - //////////////////////////////////////////////////////////////////////////// + int Write(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback); const base::File& file() const { return file_; } bool async_in_progress() const { return async_in_progress_; } @@ -90,23 +85,19 @@ class FileStream::Context { // not closed yet. void Orphan(); - void OpenAsync(const base::FilePath& path, - int open_flags, - const CompletionCallback& callback); + void Open(const base::FilePath& path, + int open_flags, + const CompletionCallback& callback); - void CloseAsync(const CompletionCallback& callback); + void Close(const CompletionCallback& callback); - void SeekAsync(Whence whence, - int64 offset, - const Int64CompletionCallback& callback); + void Seek(base::File::Whence whence, + int64 offset, + const Int64CompletionCallback& callback); - void FlushAsync(const CompletionCallback& callback); + void Flush(const CompletionCallback& callback); private: - //////////////////////////////////////////////////////////////////////////// - // Platform-independent methods implemented in file_stream_context.cc. - //////////////////////////////////////////////////////////////////////////// - struct IOResult { IOResult(); IOResult(int64 result, int os_error); @@ -129,10 +120,16 @@ class FileStream::Context { IOResult error_code; }; + //////////////////////////////////////////////////////////////////////////// + // Platform-independent methods implemented in file_stream_context.cc. + //////////////////////////////////////////////////////////////////////////// + OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); IOResult CloseFileImpl(); + IOResult FlushFileImpl(); + void OnOpenCompleted(const CompletionCallback& callback, OpenResult open_result); @@ -140,37 +137,20 @@ class FileStream::Context { Int64CompletionCallback IntToInt64(const CompletionCallback& callback); - // Called when asynchronous Open() or Seek() - // is completed. |result| contains the result or a network error code. + // Called when Open() or Seek() completes. |result| contains the result or a + // network error code. void OnAsyncCompleted(const Int64CompletionCallback& callback, const IOResult& result); //////////////////////////////////////////////////////////////////////////// - // Helper stuff which is platform-dependent but is used in the platform- - // independent code implemented in file_stream_context.cc. These helpers were - // introduced solely to implement as much of the Context methods as - // possible independently from platform. - //////////////////////////////////////////////////////////////////////////// - -#if defined(OS_WIN) - int GetLastErrno() { return GetLastError(); } - void OnAsyncFileOpened(); -#elif defined(OS_POSIX) - int GetLastErrno() { return errno; } - void OnAsyncFileOpened() {} - void CancelIo(base::PlatformFile) {} -#endif - - //////////////////////////////////////////////////////////////////////////// // Platform-dependent methods implemented in // file_stream_context_{win,posix}.cc. //////////////////////////////////////////////////////////////////////////// // Adjusts the position from where the data is read. - IOResult SeekFileImpl(Whence whence, int64 offset); + IOResult SeekFileImpl(base::File::Whence whence, int64 offset); - // Flushes all data written to the stream. - IOResult FlushFileImpl(); + void OnFileOpened(); #if defined(OS_WIN) void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); @@ -178,7 +158,7 @@ class FileStream::Context { // Implementation of MessageLoopForIO::IOHandler. virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, DWORD bytes_read, - DWORD error) OVERRIDE; + DWORD error) override; #elif defined(OS_POSIX) // ReadFileImpl() is a simple wrapper around read() that handles EINTR // signals and calls RecordAndMapError() to map errno to net error codes. diff --git a/chromium/net/base/file_stream_context_posix.cc b/chromium/net/base/file_stream_context_posix.cc index 9f3d060822f..44f59b1ef3b 100644 --- a/chromium/net/base/file_stream_context_posix.cc +++ b/chromium/net/base/file_stream_context_posix.cc @@ -2,16 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// For 64-bit file access (off_t = off64_t, lseek64, etc). -#define _FILE_OFFSET_BITS 64 - #include "net/base/file_stream_context.h" #include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> #include "base/basictypes.h" #include "base/bind.h" @@ -27,24 +20,8 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#if defined(OS_ANDROID) -// Android's bionic libc only supports the LFS transitional API. -#define off_t off64_t -#define lseek lseek64 -#define stat stat64 -#define fstat fstat64 -#endif - namespace net { -// We cast back and forth, so make sure it's the size we're expecting. -COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); - -// Make sure our Whence mappings match the system headers. -COMPILE_ASSERT(FROM_BEGIN == SEEK_SET && - FROM_CURRENT == SEEK_CUR && - FROM_END == SEEK_END, whence_matches_system); - FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner) : async_in_progress_(false), orphaned_(false), @@ -62,9 +39,9 @@ FileStream::Context::Context(base::File file, FileStream::Context::~Context() { } -int FileStream::Context::ReadAsync(IOBuffer* in_buf, - int buf_len, - const CompletionCallback& callback) { +int FileStream::Context::Read(IOBuffer* in_buf, + int buf_len, + const CompletionCallback& callback) { DCHECK(!async_in_progress_); scoped_refptr<IOBuffer> buf = in_buf; @@ -81,9 +58,9 @@ int FileStream::Context::ReadAsync(IOBuffer* in_buf, return ERR_IO_PENDING; } -int FileStream::Context::WriteAsync(IOBuffer* in_buf, - int buf_len, - const CompletionCallback& callback) { +int FileStream::Context::Write(IOBuffer* in_buf, + int buf_len, + const CompletionCallback& callback) { DCHECK(!async_in_progress_); scoped_refptr<IOBuffer> buf = in_buf; @@ -100,30 +77,23 @@ int FileStream::Context::WriteAsync(IOBuffer* in_buf, return ERR_IO_PENDING; } -FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence, - int64 offset) { - off_t res = lseek(file_.GetPlatformFile(), static_cast<off_t>(offset), - static_cast<int>(whence)); - if (res == static_cast<off_t>(-1)) +FileStream::Context::IOResult FileStream::Context::SeekFileImpl( + base::File::Whence whence, + int64 offset) { + int64 res = file_.Seek(whence, offset); + if (res == -1) return IOResult::FromOSError(errno); return IOResult(res, 0); } -FileStream::Context::IOResult FileStream::Context::FlushFileImpl() { - ssize_t res = HANDLE_EINTR(fsync(file_.GetPlatformFile())); - if (res == -1) - return IOResult::FromOSError(errno); - - return IOResult(res, 0); +void FileStream::Context::OnFileOpened() { } FileStream::Context::IOResult FileStream::Context::ReadFileImpl( scoped_refptr<IOBuffer> buf, int buf_len) { - // Loop in the case of getting interrupted by a signal. - ssize_t res = HANDLE_EINTR(read(file_.GetPlatformFile(), buf->data(), - static_cast<size_t>(buf_len))); + int res = file_.ReadAtCurrentPosNoBestEffort(buf->data(), buf_len); if (res == -1) return IOResult::FromOSError(errno); @@ -133,8 +103,7 @@ FileStream::Context::IOResult FileStream::Context::ReadFileImpl( FileStream::Context::IOResult FileStream::Context::WriteFileImpl( scoped_refptr<IOBuffer> buf, int buf_len) { - ssize_t res = HANDLE_EINTR(write(file_.GetPlatformFile(), buf->data(), - buf_len)); + int res = file_.WriteAtCurrentPosNoBestEffort(buf->data(), buf_len); if (res == -1) return IOResult::FromOSError(errno); diff --git a/chromium/net/base/file_stream_context_win.cc b/chromium/net/base/file_stream_context_win.cc index e906b6bb480..3b942d35edc 100644 --- a/chromium/net/base/file_stream_context_win.cc +++ b/chromium/net/base/file_stream_context_win.cc @@ -15,11 +15,6 @@ namespace net { -// Ensure that we can just use our Whence values directly. -COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); -COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); -COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); - namespace { void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { @@ -57,16 +52,16 @@ FileStream::Context::Context(base::File file, memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); if (file_.IsValid()) { // TODO(hashimoto): Check that file_ is async. - OnAsyncFileOpened(); + OnFileOpened(); } } FileStream::Context::~Context() { } -int FileStream::Context::ReadAsync(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) { +int FileStream::Context::Read(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { DCHECK(!async_in_progress_); DWORD bytes_read; @@ -87,9 +82,9 @@ int FileStream::Context::ReadAsync(IOBuffer* buf, return ERR_IO_PENDING; } -int FileStream::Context::WriteAsync(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) { +int FileStream::Context::Write(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { DWORD bytes_written = 0; if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, &bytes_written, &io_context_.overlapped)) { @@ -106,29 +101,22 @@ int FileStream::Context::WriteAsync(IOBuffer* buf, return ERR_IO_PENDING; } -void FileStream::Context::OnAsyncFileOpened() { - base::MessageLoopForIO::current()->RegisterIOHandler(file_.GetPlatformFile(), - this); -} - -FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence, - int64 offset) { - LARGE_INTEGER distance, res; - distance.QuadPart = offset; - DWORD move_method = static_cast<DWORD>(whence); - if (SetFilePointerEx(file_.GetPlatformFile(), distance, &res, move_method)) { - SetOffset(&io_context_.overlapped, res); - return IOResult(res.QuadPart, 0); +FileStream::Context::IOResult FileStream::Context::SeekFileImpl( + base::File::Whence whence, + int64 offset) { + LARGE_INTEGER result; + result.QuadPart = file_.Seek(whence, offset); + if (result.QuadPart >= 0) { + SetOffset(&io_context_.overlapped, result); + return IOResult(result.QuadPart, 0); } return IOResult::FromOSError(GetLastError()); } -FileStream::Context::IOResult FileStream::Context::FlushFileImpl() { - if (FlushFileBuffers(file_.GetPlatformFile())) - return IOResult(OK, 0); - - return IOResult::FromOSError(GetLastError()); +void FileStream::Context::OnFileOpened() { + base::MessageLoopForIO::current()->RegisterIOHandler(file_.GetPlatformFile(), + this); } void FileStream::Context::IOCompletionIsPending( diff --git a/chromium/net/base/file_stream_unittest.cc b/chromium/net/base/file_stream_unittest.cc index 292b0d207cf..fc9257e5d1c 100644 --- a/chromium/net/base/file_stream_unittest.cc +++ b/chromium/net/base/file_stream_unittest.cc @@ -6,12 +6,13 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/file_util.h" #include "base/files/file.h" +#include "base/files/file_util.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "base/threading/sequenced_worker_pool.h" @@ -45,13 +46,13 @@ IOBufferWithSize* CreateTestDataBuffer() { class FileStreamTest : public PlatformTest { public: - virtual void SetUp() { + void SetUp() override { PlatformTest::SetUp(); base::CreateTemporaryFile(&temp_file_path_); base::WriteFile(temp_file_path_, kTestData, kTestDataSize); } - virtual void TearDown() { + void TearDown() override { // FileStreamContexts must be asynchronously closed on the file task runner // before they can be deleted. Pump the RunLoop to avoid leaks. base::RunLoop().RunUntilIdle(); @@ -68,7 +69,7 @@ class FileStreamTest : public PlatformTest { namespace { -TEST_F(FileStreamTest, AsyncOpenExplicitClose) { +TEST_F(FileStreamTest, OpenExplicitClose) { TestCompletionCallback callback; FileStream stream(base::MessageLoopProxy::current()); int flags = base::File::FLAG_OPEN | @@ -85,7 +86,7 @@ TEST_F(FileStreamTest, AsyncOpenExplicitClose) { EXPECT_FALSE(stream.GetFileForTesting().IsValid()); } -TEST_F(FileStreamTest, AsyncOpenExplicitCloseOrphaned) { +TEST_F(FileStreamTest, OpenExplicitCloseOrphaned) { TestCompletionCallback callback; scoped_ptr<FileStream> stream(new FileStream( base::MessageLoopProxy::current())); @@ -120,7 +121,8 @@ TEST_F(FileStreamTest, UseFileHandle) { scoped_ptr<FileStream> read_stream( new FileStream(file.Pass(), base::MessageLoopProxy::current())); ASSERT_EQ(ERR_IO_PENDING, - read_stream->Seek(FROM_BEGIN, 0, callback64.callback())); + read_stream->Seek(base::File::FROM_BEGIN, 0, + callback64.callback())); ASSERT_EQ(0, callback64.WaitForResult()); // Read into buffer and compare. scoped_refptr<IOBufferWithSize> read_buffer = @@ -139,7 +141,8 @@ TEST_F(FileStreamTest, UseFileHandle) { scoped_ptr<FileStream> write_stream( new FileStream(file.Pass(), base::MessageLoopProxy::current())); ASSERT_EQ(ERR_IO_PENDING, - write_stream->Seek(FROM_BEGIN, 0, callback64.callback())); + write_stream->Seek(base::File::FROM_BEGIN, 0, + callback64.callback())); ASSERT_EQ(0, callback64.WaitForResult()); scoped_refptr<IOBufferWithSize> write_buffer = CreateTestDataBuffer(); rv = write_stream->Write(write_buffer.get(), kTestDataSize, @@ -164,16 +167,16 @@ TEST_F(FileStreamTest, UseClosedStream) { EXPECT_FALSE(stream.IsOpen()); // Try seeking... - rv = stream.Seek(FROM_BEGIN, 5, callback64.callback()); + rv = stream.Seek(base::File::FROM_BEGIN, 5, callback64.callback()); EXPECT_EQ(ERR_UNEXPECTED, callback64.GetResult(rv)); // Try reading... scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(10); - rv = stream.Read(buf, buf->size(), callback.callback()); + rv = stream.Read(buf.get(), buf->size(), callback.callback()); EXPECT_EQ(ERR_UNEXPECTED, callback.GetResult(rv)); } -TEST_F(FileStreamTest, AsyncRead) { +TEST_F(FileStreamTest, Read) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -182,8 +185,7 @@ TEST_F(FileStreamTest, AsyncRead) { base::File::FLAG_ASYNC; TestCompletionCallback callback; int rv = stream.Open(temp_file_path(), flags, callback.callback()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_EQ(OK, callback.GetResult(rv)); int total_bytes_read = 0; @@ -191,8 +193,7 @@ TEST_F(FileStreamTest, AsyncRead) { for (;;) { scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); rv = stream.Read(buf.get(), buf->size(), callback.callback()); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); + rv = callback.GetResult(rv); EXPECT_LE(0, rv); if (rv <= 0) break; @@ -203,7 +204,7 @@ TEST_F(FileStreamTest, AsyncRead) { EXPECT_EQ(kTestData, data_read); } -TEST_F(FileStreamTest, AsyncRead_EarlyDelete) { +TEST_F(FileStreamTest, Read_EarlyDelete) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -229,7 +230,7 @@ TEST_F(FileStreamTest, AsyncRead_EarlyDelete) { } } -TEST_F(FileStreamTest, AsyncRead_FromOffset) { +TEST_F(FileStreamTest, Read_FromOffset) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -243,7 +244,7 @@ TEST_F(FileStreamTest, AsyncRead_FromOffset) { TestInt64CompletionCallback callback64; const int64 kOffset = 3; - rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback()); + rv = stream.Seek(base::File::FROM_BEGIN, kOffset, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); int64 new_offset = callback64.WaitForResult(); EXPECT_EQ(kOffset, new_offset); @@ -266,7 +267,7 @@ TEST_F(FileStreamTest, AsyncRead_FromOffset) { EXPECT_EQ(kTestData + kOffset, data_read); } -TEST_F(FileStreamTest, AsyncSeekAround) { +TEST_F(FileStreamTest, SeekAround) { FileStream stream(base::MessageLoopProxy::current()); int flags = base::File::FLAG_OPEN | base::File::FLAG_ASYNC | base::File::FLAG_READ; @@ -278,63 +279,55 @@ TEST_F(FileStreamTest, AsyncSeekAround) { TestInt64CompletionCallback callback64; const int64 kOffset = 3; - rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback()); + rv = stream.Seek(base::File::FROM_BEGIN, kOffset, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); int64 new_offset = callback64.WaitForResult(); EXPECT_EQ(kOffset, new_offset); - rv = stream.Seek(FROM_CURRENT, kOffset, callback64.callback()); + rv = stream.Seek(base::File::FROM_CURRENT, kOffset, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); new_offset = callback64.WaitForResult(); EXPECT_EQ(2 * kOffset, new_offset); - rv = stream.Seek(FROM_CURRENT, -kOffset, callback64.callback()); + rv = stream.Seek(base::File::FROM_CURRENT, -kOffset, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); new_offset = callback64.WaitForResult(); EXPECT_EQ(kOffset, new_offset); const int kTestDataLen = arraysize(kTestData) - 1; - rv = stream.Seek(FROM_END, -kTestDataLen, callback64.callback()); + rv = stream.Seek(base::File::FROM_END, -kTestDataLen, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); new_offset = callback64.WaitForResult(); EXPECT_EQ(0, new_offset); } -TEST_F(FileStreamTest, AsyncWrite) { +TEST_F(FileStreamTest, Write) { FileStream stream(base::MessageLoopProxy::current()); int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | base::File::FLAG_ASYNC; TestCompletionCallback callback; int rv = stream.Open(temp_file_path(), flags, callback.callback()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_EQ(OK, callback.GetResult(rv)); int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); EXPECT_EQ(0, file_size); - int total_bytes_written = 0; + scoped_refptr<IOBuffer> buf = CreateTestDataBuffer(); + rv = stream.Write(buf.get(), kTestDataSize, callback.callback()); + rv = callback.GetResult(rv); + EXPECT_EQ(kTestDataSize, rv); - scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); - scoped_refptr<DrainableIOBuffer> drainable = - new DrainableIOBuffer(buf.get(), buf->size()); - while (total_bytes_written != kTestDataSize) { - rv = stream.Write(drainable.get(), drainable->BytesRemaining(), - callback.callback()); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - EXPECT_LT(0, rv); - if (rv <= 0) - break; - drainable->DidConsume(rv); - total_bytes_written += rv; - } EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); - EXPECT_EQ(file_size, total_bytes_written); + EXPECT_EQ(kTestDataSize, file_size); + + std::string data_read; + EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &data_read)); + EXPECT_EQ(kTestData, data_read); } -TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) { +TEST_F(FileStreamTest, Write_EarlyDelete) { scoped_ptr<FileStream> stream( new FileStream(base::MessageLoopProxy::current())); int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | @@ -362,7 +355,7 @@ TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) { } } -TEST_F(FileStreamTest, AsyncWrite_FromOffset) { +TEST_F(FileStreamTest, Write_FromOffset) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -376,7 +369,7 @@ TEST_F(FileStreamTest, AsyncWrite_FromOffset) { TestInt64CompletionCallback callback64; const int64 kOffset = 0; - rv = stream.Seek(FROM_END, kOffset, callback64.callback()); + rv = stream.Seek(base::File::FROM_END, kOffset, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); int64 new_offset = callback64.WaitForResult(); EXPECT_EQ(kTestDataSize, new_offset); @@ -401,7 +394,7 @@ TEST_F(FileStreamTest, AsyncWrite_FromOffset) { EXPECT_EQ(file_size, kTestDataSize * 2); } -TEST_F(FileStreamTest, BasicAsyncReadWrite) { +TEST_F(FileStreamTest, BasicReadWrite) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -454,7 +447,7 @@ TEST_F(FileStreamTest, BasicAsyncReadWrite) { EXPECT_EQ(kTestDataSize * 2, file_size); } -TEST_F(FileStreamTest, BasicAsyncWriteRead) { +TEST_F(FileStreamTest, BasicWriteRead) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -468,7 +461,7 @@ TEST_F(FileStreamTest, BasicAsyncWriteRead) { EXPECT_EQ(OK, callback.WaitForResult()); TestInt64CompletionCallback callback64; - rv = stream->Seek(FROM_END, 0, callback64.callback()); + rv = stream->Seek(base::File::FROM_END, 0, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); int64 offset = callback64.WaitForResult(); EXPECT_EQ(offset, file_size); @@ -492,7 +485,7 @@ TEST_F(FileStreamTest, BasicAsyncWriteRead) { EXPECT_EQ(kTestDataSize, total_bytes_written); - rv = stream->Seek(FROM_BEGIN, 0, callback64.callback()); + rv = stream->Seek(base::File::FROM_BEGIN, 0, callback64.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); offset = callback64.WaitForResult(); EXPECT_EQ(0, offset); @@ -577,7 +570,8 @@ class TestWriteReadCompletionCallback { } else { // We're done writing all data. Start reading the data. TestInt64CompletionCallback callback64; EXPECT_EQ(ERR_IO_PENDING, - stream_->Seek(FROM_BEGIN, 0, callback64.callback())); + stream_->Seek(base::File::FROM_BEGIN, 0, + callback64.callback())); { base::MessageLoop::ScopedNestableTaskAllower allow( base::MessageLoop::current()); @@ -621,7 +615,7 @@ class TestWriteReadCompletionCallback { DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback); }; -TEST_F(FileStreamTest, AsyncWriteRead) { +TEST_F(FileStreamTest, WriteRead) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -635,7 +629,8 @@ TEST_F(FileStreamTest, AsyncWriteRead) { EXPECT_EQ(OK, open_callback.WaitForResult()); TestInt64CompletionCallback callback64; - EXPECT_EQ(ERR_IO_PENDING, stream->Seek(FROM_END, 0, callback64.callback())); + EXPECT_EQ(ERR_IO_PENDING, + stream->Seek(base::File::FROM_END, 0, callback64.callback())); EXPECT_EQ(file_size, callback64.WaitForResult()); int total_bytes_written = 0; @@ -725,7 +720,7 @@ class TestWriteCloseCompletionCallback { DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback); }; -TEST_F(FileStreamTest, AsyncWriteClose) { +TEST_F(FileStreamTest, WriteClose) { int64 file_size; EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size)); @@ -739,7 +734,8 @@ TEST_F(FileStreamTest, AsyncWriteClose) { EXPECT_EQ(OK, open_callback.WaitForResult()); TestInt64CompletionCallback callback64; - EXPECT_EQ(ERR_IO_PENDING, stream->Seek(FROM_END, 0, callback64.callback())); + EXPECT_EQ(ERR_IO_PENDING, + stream->Seek(base::File::FROM_END, 0, callback64.callback())); EXPECT_EQ(file_size, callback64.WaitForResult()); int total_bytes_written = 0; @@ -758,7 +754,7 @@ TEST_F(FileStreamTest, AsyncWriteClose) { EXPECT_EQ(kTestDataSize * 2, file_size); } -TEST_F(FileStreamTest, AsyncOpenAndDelete) { +TEST_F(FileStreamTest, OpenAndDelete) { scoped_refptr<base::SequencedWorkerPool> pool( new base::SequencedWorkerPool(1, "StreamTest")); @@ -789,8 +785,8 @@ TEST_F(FileStreamTest, AsyncOpenAndDelete) { base::ThreadRestrictions::SetIOAllowed(prev); } -// Verify that async Write() errors are mapped correctly. -TEST_F(FileStreamTest, AsyncWriteError) { +// Verify that Write() errors are mapped correctly. +TEST_F(FileStreamTest, WriteError) { // Try opening file as read-only and then writing to it using FileStream. uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC; @@ -814,8 +810,8 @@ TEST_F(FileStreamTest, AsyncWriteError) { base::RunLoop().RunUntilIdle(); } -// Verify that async Read() errors are mapped correctly. -TEST_F(FileStreamTest, AsyncReadError) { +// Verify that Read() errors are mapped correctly. +TEST_F(FileStreamTest, ReadError) { // Try opening file for write and then reading from it using FileStream. uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE | base::File::FLAG_ASYNC; @@ -838,7 +834,7 @@ TEST_F(FileStreamTest, AsyncReadError) { } #if defined(OS_ANDROID) -TEST_F(FileStreamTest, ContentUriAsyncRead) { +TEST_F(FileStreamTest, ContentUriRead) { base::FilePath test_dir; PathService::Get(base::DIR_SOURCE_ROOT, &test_dir); test_dir = test_dir.AppendASCII("net"); @@ -849,7 +845,7 @@ TEST_F(FileStreamTest, ContentUriAsyncRead) { // Insert the image into MediaStore. MediaStore will do some conversions, and // return the content URI. - base::FilePath path = file_util::InsertImageIntoMediaStore(image_file); + base::FilePath path = base::InsertImageIntoMediaStore(image_file); EXPECT_TRUE(path.IsContentUri()); EXPECT_TRUE(base::PathExists(path)); int64 file_size; diff --git a/chromium/net/base/file_stream_whence.h b/chromium/net/base/file_stream_whence.h deleted file mode 100644 index a962341f93d..00000000000 --- a/chromium/net/base/file_stream_whence.h +++ /dev/null @@ -1,20 +0,0 @@ -// 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 NET_BASE_FILE_STREAM_WHENCE_H_ -#define NET_BASE_FILE_STREAM_WHENCE_H_ - -namespace net { - -// TODO(darin): Move this to a more generic location. -// This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. -enum Whence { - FROM_BEGIN = 0, - FROM_CURRENT = 1, - FROM_END = 2 -}; - -} // namespace net - -#endif // NET_BASE_FILE_STREAM_WHENCE_H_ diff --git a/chromium/net/base/filename_util.cc b/chromium/net/base/filename_util.cc index 31b5fe5ec70..6573c226161 100644 --- a/chromium/net/base/filename_util.cc +++ b/chromium/net/base/filename_util.cc @@ -4,8 +4,8 @@ #include "net/base/filename_util.h" -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" diff --git a/chromium/net/base/filename_util_icu.cc b/chromium/net/base/filename_util_icu.cc index 72bce6e0c36..8c22eec9520 100644 --- a/chromium/net/base/filename_util_icu.cc +++ b/chromium/net/base/filename_util_icu.cc @@ -24,7 +24,7 @@ bool IsSafePortablePathComponent(const base::FilePath& component) { return !component.empty() && (component == component.BaseName()) && (component == component.StripTrailingSeparators()) && FilePathToString16(component, &component16) && - file_util::IsFilenameLegal(component16) && + base::i18n::IsFilenameLegal(component16) && !IsShellIntegratedExtension(extension) && (sanitized == component.value()) && !IsReservedName(component.value()); } @@ -56,7 +56,7 @@ base::string16 GetSuggestedFilename(const GURL& url, suggested_name, mime_type, default_name, - base::Bind(&file_util::ReplaceIllegalCharactersInPath)); + base::Bind(&base::i18n::ReplaceIllegalCharactersInPath)); } base::FilePath GenerateFileName(const GURL& url, @@ -72,14 +72,14 @@ base::FilePath GenerateFileName(const GURL& url, suggested_name, mime_type, default_file_name, - base::Bind(&file_util::ReplaceIllegalCharactersInPath))); + base::Bind(&base::i18n::ReplaceIllegalCharactersInPath))); #if defined(OS_CHROMEOS) // When doing file manager operations on ChromeOS, the file paths get // normalized in WebKit layer, so let's ensure downloaded files have // normalized names. Otherwise, we won't be able to handle files with NFD // utf8 encoded characters in name. - file_util::NormalizeFileNameEncoding(&generated_name); + base::i18n::NormalizeFileNameEncoding(&generated_name); #endif DCHECK(!generated_name.empty()); diff --git a/chromium/net/base/filename_util_internal.cc b/chromium/net/base/filename_util_internal.cc index a59de0f50c9..be9139dfff5 100644 --- a/chromium/net/base/filename_util_internal.cc +++ b/chromium/net/base/filename_util_internal.cc @@ -4,9 +4,8 @@ #include "net/base/filename_util.h" -#include "base/file_util.h" #include "base/files/file_path.h" -#include "base/path_service.h" +#include "base/files/file_util.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -89,7 +88,8 @@ std::string GetFileNameFromURL(const GURL& url, // Returns whether the specified extension is automatically integrated into the // windows shell. bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) { - base::FilePath::StringType extension_lower = StringToLowerASCII(extension); + base::FilePath::StringType extension_lower = + base::StringToLowerASCII(extension); // http://msdn.microsoft.com/en-us/library/ms811694.aspx // Right-clicking on shortcuts can be magical. @@ -119,9 +119,10 @@ bool IsReservedName(const base::FilePath::StringType& filename) { "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "clock$"}; #if defined(OS_WIN) - std::string filename_lower = StringToLowerASCII(base::WideToUTF8(filename)); + std::string filename_lower = + base::StringToLowerASCII(base::WideToUTF8(filename)); #elif defined(OS_POSIX) - std::string filename_lower = StringToLowerASCII(filename); + std::string filename_lower = base::StringToLowerASCII(filename); #endif for (size_t i = 0; i < arraysize(known_devices); ++i) { @@ -227,11 +228,13 @@ base::string16 GetSuggestedFilenameImpl( FILE_PATH_LITERAL("download"); std::string filename; // In UTF-8 bool overwrite_extension = false; - + bool is_name_from_content_disposition = false; // Try to extract a filename from content-disposition first. if (!content_disposition.empty()) { HttpContentDisposition header(content_disposition, referrer_charset); filename = header.filename(); + if (!filename.empty()) + is_name_from_content_disposition = true; } // Then try to use the suggested name. @@ -273,7 +276,13 @@ base::string16 GetSuggestedFilenameImpl( } replace_illegal_characters_callback.Run(&result_str, '-'); base::FilePath result(result_str); - GenerateSafeFileName(mime_type, overwrite_extension, &result); + // extension should not appended to filename derived from + // content-disposition, if it does not have one. + // Hence mimetype and overwrite_extension values are not used. + if (is_name_from_content_disposition) + GenerateSafeFileName("", false, &result); + else + GenerateSafeFileName(mime_type, overwrite_extension, &result); base::string16 result16; if (!FilePathToString16(result, &result16)) { diff --git a/chromium/net/base/filename_util_unittest.cc b/chromium/net/base/filename_util_unittest.cc index 0bd22500fe9..391baeb3312 100644 --- a/chromium/net/base/filename_util_unittest.cc +++ b/chromium/net/base/filename_util_unittest.cc @@ -4,8 +4,8 @@ #include "net/base/filename_util.h" -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/test_file_util.h" @@ -32,14 +32,29 @@ struct GenerateFilenameCase { const wchar_t* expected_filename; }; +// The expected filenames are coded as wchar_t for convenience. +std::wstring FilePathAsWString(const base::FilePath& path) { +#if defined(OS_WIN) + return path.value(); +#else + return base::UTF8ToWide(path.value()); +#endif +} +base::FilePath WStringAsFilePath(const std::wstring& str) { +#if defined(OS_WIN) + return base::FilePath(str); +#else + return base::FilePath(base::WideToUTF8(str)); +#endif +} + void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) { std::string default_filename(base::WideToUTF8(test_case->default_filename)); base::FilePath file_path = GenerateFileName( GURL(test_case->url), test_case->content_disp_header, test_case->referrer_charset, test_case->suggested_filename, test_case->mime_type, default_filename); - EXPECT_EQ(test_case->expected_filename, - file_util::FilePathAsWString(file_path)) + EXPECT_EQ(test_case->expected_filename, FilePathAsWString(file_path)) << "test case at line number: " << test_case->lineno; } @@ -168,15 +183,15 @@ TEST(FilenameUtilTest, FileURLConversion) { // First, we'll test that we can round-trip all of the above cases of URLs base::FilePath output; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(round_trip_cases); i++) { + for (size_t i = 0; i < arraysize(round_trip_cases); i++) { // convert to the file URL GURL file_url(FilePathToFileURL( - file_util::WStringAsFilePath(round_trip_cases[i].file))); + WStringAsFilePath(round_trip_cases[i].file))); EXPECT_EQ(round_trip_cases[i].url, file_url.spec()); // Back to the filename. EXPECT_TRUE(FileURLToFilePath(file_url, &output)); - EXPECT_EQ(round_trip_cases[i].file, file_util::FilePathAsWString(output)); + EXPECT_EQ(round_trip_cases[i].file, FilePathAsWString(output)); } // Test that various file: URLs get decoded into the correct file type @@ -213,9 +228,9 @@ TEST(FilenameUtilTest, FileURLConversion) { //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"}, #endif }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_cases); i++) { + for (size_t i = 0; i < arraysize(url_cases); i++) { FileURLToFilePath(GURL(url_cases[i].url), &output); - EXPECT_EQ(url_cases[i].file, file_util::FilePathAsWString(output)); + EXPECT_EQ(url_cases[i].file, FilePathAsWString(output)); } // Unfortunately, UTF8ToWide discards invalid UTF8 input. @@ -394,7 +409,7 @@ TEST(FilenameUtilTest, GenerateSafeFileName) { #endif // !defined(OS_WIN) }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(safe_tests); ++i) { + for (size_t i = 0; i < arraysize(safe_tests); ++i) { base::FilePath file_path(safe_tests[i].filename); GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path); EXPECT_EQ(safe_tests[i].expected_filename, file_path.value()) @@ -408,7 +423,7 @@ TEST(FilenameUtilTest, GenerateFileName) { // string conversions fail. This is OK (we have the default value) but they // don't match our expectations. std::string locale = setlocale(LC_CTYPE, NULL); - StringToLowerASCII(&locale); + base::StringToLowerASCII(&locale); EXPECT_TRUE(locale.find("utf-8") != std::string::npos || locale.find("utf8") != std::string::npos) << "Your locale (" << locale << ") must be set to UTF-8 " @@ -795,6 +810,16 @@ TEST(FilenameUtilTest, GenerateFileName) { L"", L"test.html" }, + { + __LINE__, + "http://www.google.com/test", + "attachment; filename=test", + "utf-8", + "", + "image/png", + L"", + L"test" + }, #if 0 { // The filename encoding doesn't match the referrer charset, the system // charset, or UTF-8. @@ -1007,7 +1032,7 @@ TEST(FilenameUtilTest, GenerateFileName) { "", "text/plain", L"default", - L"-blink-Hello kitty--blink-" TXT_EXT + L"-blink-Hello kitty--blink-" }, { // A normal avi should get .avi and not .avi.avi __LINE__, @@ -1027,7 +1052,7 @@ TEST(FilenameUtilTest, GenerateFileName) { "", "image/jpeg", L"download", - L"my-cat" JPEG_EXT + L"my-cat" }, { __LINE__, @@ -1037,7 +1062,7 @@ TEST(FilenameUtilTest, GenerateFileName) { "", "text/plain", L"download", - L"my-cat.txt" + L"my-cat" }, { __LINE__, @@ -1047,7 +1072,7 @@ TEST(FilenameUtilTest, GenerateFileName) { "", "text/html", L"download", - L"my-cat" HTML_EXT + L"my-cat" }, { // Unknown MIME type __LINE__, @@ -1271,7 +1296,7 @@ TEST(FilenameUtilTest, GenerateFileName) { "", "text/plain", L"download", - L"hidden" TXT_EXT + L"hidden" }, { __LINE__, @@ -1296,9 +1321,9 @@ TEST(FilenameUtilTest, GenerateFileName) { "text/plain", L"download", #if defined(OS_WIN) - L"trailing-" TXT_EXT + L"trailing-" #else - L"trailing" TXT_EXT + L"trailing" #endif }, { @@ -1636,13 +1661,13 @@ TEST(FilenameUtilTest, GenerateFileName) { #endif }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(selection_tests); ++i) + for (size_t i = 0; i < arraysize(selection_tests); ++i) RunGenerateFileNameTestCase(&selection_tests[i]); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) + for (size_t i = 0; i < arraysize(generation_tests); ++i) RunGenerateFileNameTestCase(&generation_tests[i]); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) { + for (size_t i = 0; i < arraysize(generation_tests); ++i) { GenerateFilenameCase test_case = generation_tests[i]; test_case.referrer_charset = "GBK"; RunGenerateFileNameTestCase(&test_case); diff --git a/chromium/net/base/host_mapping_rules.cc b/chromium/net/base/host_mapping_rules.cc index 6ae475458b0..f91f3fd0b4e 100644 --- a/chromium/net/base/host_mapping_rules.cc +++ b/chromium/net/base/host_mapping_rules.cc @@ -74,7 +74,7 @@ bool HostMappingRules::AddRuleFromString(const std::string& rule_string) { // Test for EXCLUSION rule. if (parts.size() == 2 && LowerCaseEqualsASCII(parts[0], "exclude")) { ExclusionRule rule; - rule.hostname_pattern = StringToLowerASCII(parts[1]); + rule.hostname_pattern = base::StringToLowerASCII(parts[1]); exclusion_rules_.push_back(rule); return true; } @@ -82,7 +82,7 @@ bool HostMappingRules::AddRuleFromString(const std::string& rule_string) { // Test for MAP rule. if (parts.size() == 3 && LowerCaseEqualsASCII(parts[0], "map")) { MapRule rule; - rule.hostname_pattern = StringToLowerASCII(parts[1]); + rule.hostname_pattern = base::StringToLowerASCII(parts[1]); if (!ParseHostAndPort(parts[2], &rule.replacement_hostname, &rule.replacement_port)) { diff --git a/chromium/net/base/io_buffer.cc b/chromium/net/base/io_buffer.cc index dd1d4517eea..a375381bfd9 100644 --- a/chromium/net/base/io_buffer.cc +++ b/chromium/net/base/io_buffer.cc @@ -46,6 +46,13 @@ StringIOBuffer::StringIOBuffer(const std::string& s) data_ = const_cast<char*>(string_data_.data()); } +StringIOBuffer::StringIOBuffer(scoped_ptr<std::string> s) + : IOBuffer(static_cast<char*>(NULL)) { + CHECK_LT(s->size(), static_cast<size_t>(INT_MAX)); + string_data_.swap(*s.get()); + data_ = const_cast<char*>(string_data_.data()); +} + StringIOBuffer::~StringIOBuffer() { // We haven't allocated the buffer, so remove it before the base class // destructor tries to delete[] it. diff --git a/chromium/net/base/io_buffer.h b/chromium/net/base/io_buffer.h index 0ce52e8d79c..04bbc883e97 100644 --- a/chromium/net/base/io_buffer.h +++ b/chromium/net/base/io_buffer.h @@ -104,7 +104,7 @@ class NET_EXPORT IOBufferWithSize : public IOBuffer { // constructor IOBuffer(char*) thus allowing subclass to use underlying // memory it does not own. IOBufferWithSize(char* data, int size); - virtual ~IOBufferWithSize(); + ~IOBufferWithSize() override; int size_; }; @@ -114,11 +114,12 @@ class NET_EXPORT IOBufferWithSize : public IOBuffer { class NET_EXPORT StringIOBuffer : public IOBuffer { public: explicit StringIOBuffer(const std::string& s); + explicit StringIOBuffer(scoped_ptr<std::string> s); int size() const { return static_cast<int>(string_data_.size()); } private: - virtual ~StringIOBuffer(); + ~StringIOBuffer() override; std::string string_data_; }; @@ -161,7 +162,7 @@ class NET_EXPORT DrainableIOBuffer : public IOBuffer { int size() const { return size_; } private: - virtual ~DrainableIOBuffer(); + ~DrainableIOBuffer() override; scoped_refptr<IOBuffer> base_; int size_; @@ -201,7 +202,7 @@ class NET_EXPORT GrowableIOBuffer : public IOBuffer { char* StartOfBuffer(); private: - virtual ~GrowableIOBuffer(); + ~GrowableIOBuffer() override; scoped_ptr<char, base::FreeDeleter> real_data_; int capacity_; @@ -221,7 +222,7 @@ class NET_EXPORT PickledIOBuffer : public IOBuffer { void Done(); private: - virtual ~PickledIOBuffer(); + ~PickledIOBuffer() override; Pickle pickle_; }; @@ -236,7 +237,7 @@ class NET_EXPORT WrappedIOBuffer : public IOBuffer { explicit WrappedIOBuffer(const char* data); protected: - virtual ~WrappedIOBuffer(); + ~WrappedIOBuffer() override; }; } // namespace net diff --git a/chromium/net/base/ip_endpoint_unittest.cc b/chromium/net/base/ip_endpoint_unittest.cc index f10e8e99737..5d709115207 100644 --- a/chromium/net/base/ip_endpoint_unittest.cc +++ b/chromium/net/base/ip_endpoint_unittest.cc @@ -29,11 +29,11 @@ struct TestData { { "::1", "[::1]", true }, { "2001:db8:0::42", "[2001:db8::42]", true }, }; -int test_count = ARRAYSIZE_UNSAFE(tests); +int test_count = arraysize(tests); class IPEndPointTest : public PlatformTest { public: - virtual void SetUp() { + void SetUp() override { // This is where we populate the TestData. for (int index = 0; index < test_count; ++index) { EXPECT_TRUE(ParseIPLiteralToNumber(tests[index].host, diff --git a/chromium/net/base/keygen_handler_nss.cc b/chromium/net/base/keygen_handler_nss.cc index ad0f0ebe672..661dabc7710 100644 --- a/chromium/net/base/keygen_handler_nss.cc +++ b/chromium/net/base/keygen_handler_nss.cc @@ -7,7 +7,6 @@ #include "base/logging.h" #include "crypto/nss_crypto_module_delegate.h" #include "crypto/nss_util.h" -#include "crypto/nss_util_internal.h" #include "crypto/scoped_nss_types.h" #include "net/third_party/mozilla_security_manager/nsKeygenHandler.h" @@ -17,26 +16,21 @@ namespace psm = mozilla_security_manager; namespace net { std::string KeygenHandler::GenKeyAndSignChallenge() { - // Ensure NSS is initialized. crypto::EnsureNSSInit(); crypto::ScopedPK11Slot slot; - if (crypto_module_delegate_) + if (crypto_module_delegate_) { slot = crypto_module_delegate_->RequestSlot().Pass(); - else - slot.reset(crypto::GetPrivateNSSKeySlot()); - if (!slot.get()) { - LOG(ERROR) << "Couldn't get private key slot from NSS!"; + } else { + LOG(ERROR) << "Could not get an NSS key slot."; return std::string(); } // Authenticate to the token. - if (SECSuccess != - PK11_Authenticate( - slot.get(), - PR_TRUE, - crypto_module_delegate_ ? crypto_module_delegate_->wincx() : NULL)) { - LOG(ERROR) << "Couldn't authenticate to private key slot!"; + if (SECSuccess != PK11_Authenticate(slot.get(), + PR_TRUE, + crypto_module_delegate_->wincx())) { + LOG(ERROR) << "Could not authenticate to the key slot."; return std::string(); } diff --git a/chromium/net/base/keygen_handler_openssl.cc b/chromium/net/base/keygen_handler_openssl.cc index edd0eb110b4..aeb64a8b543 100644 --- a/chromium/net/base/keygen_handler_openssl.cc +++ b/chromium/net/base/keygen_handler_openssl.cc @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" +#include "crypto/scoped_openssl_types.h" #include "net/base/openssl_private_key_store.h" namespace net { @@ -22,8 +23,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { if (stores_key_) OpenSSLPrivateKeyStore::StoreKeyPair(url_, pkey); - crypto::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free> spki( - NETSCAPE_SPKI_new()); + crypto::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free>::Type spki( + NETSCAPE_SPKI_new()); ASN1_STRING_set(spki.get()->spkac->challenge, challenge_.data(), challenge_.size()); NETSCAPE_SPKI_set_pubkey(spki.get(), pkey); diff --git a/chromium/net/base/keygen_handler_unittest.cc b/chromium/net/base/keygen_handler_unittest.cc index 85c3844c067..2357328e42c 100644 --- a/chromium/net/base/keygen_handler_unittest.cc +++ b/chromium/net/base/keygen_handler_unittest.cc @@ -14,27 +14,60 @@ #include "base/threading/thread_restrictions.h" #include "base/synchronization/waitable_event.h" #include "build/build_config.h" -#include "crypto/nss_util.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(USE_NSS) #include <private/pprthred.h> // PR_DetachThread +#include "crypto/nss_crypto_module_delegate.h" +#include "crypto/scoped_test_nss_db.h" #endif namespace net { namespace { +#if defined(USE_NSS) +class StubCryptoModuleDelegate : public crypto::NSSCryptoModuleDelegate { + public: + explicit StubCryptoModuleDelegate(crypto::ScopedPK11Slot slot) + : slot_(slot.Pass()) {} + + std::string RequestPassword(const std::string& slot_name, + bool retry, + bool* cancelled) override { + return std::string(); + } + + crypto::ScopedPK11Slot RequestSlot() override { + return crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot_.get())); + } + + private: + crypto::ScopedPK11Slot slot_; +}; +#endif + class KeygenHandlerTest : public ::testing::Test { public: KeygenHandlerTest() {} - virtual ~KeygenHandlerTest() {} + ~KeygenHandlerTest() override {} - virtual void SetUp() { -#if defined(OS_CHROMEOS) && defined(USE_NSS) - crypto::OpenPersistentNSSDB(); + scoped_ptr<KeygenHandler> CreateKeygenHandler() { + scoped_ptr<KeygenHandler> handler(new KeygenHandler( + 768, "some challenge", GURL("http://www.example.com"))); +#if defined(USE_NSS) + handler->set_crypto_module_delegate( + scoped_ptr<crypto::NSSCryptoModuleDelegate>( + new StubCryptoModuleDelegate(crypto::ScopedPK11Slot( + PK11_ReferenceSlot(test_nss_db_.slot()))))); #endif + return handler.Pass(); } + + private: +#if defined(USE_NSS) + crypto::ScopedTestNSSDB test_nss_db_; +#endif }; // Assert that |result| is a valid output for KeygenHandler given challenge @@ -74,22 +107,22 @@ void AssertValidSignedPublicKeyAndChallenge(const std::string& result, } TEST_F(KeygenHandlerTest, SmokeTest) { - KeygenHandler handler(768, "some challenge", GURL("http://www.example.com")); - handler.set_stores_key(false); // Don't leave the key-pair behind - std::string result = handler.GenKeyAndSignChallenge(); + scoped_ptr<KeygenHandler> handler(CreateKeygenHandler()); + handler->set_stores_key(false); // Don't leave the key-pair behind + std::string result = handler->GenKeyAndSignChallenge(); VLOG(1) << "KeygenHandler produced: " << result; AssertValidSignedPublicKeyAndChallenge(result, "some challenge"); } -void ConcurrencyTestCallback(base::WaitableEvent* event, - const std::string& challenge, +void ConcurrencyTestCallback(const std::string& challenge, + base::WaitableEvent* event, + scoped_ptr<KeygenHandler> handler, std::string* result) { // We allow Singleton use on the worker thread here since we use a // WaitableEvent to synchronize, so it's safe. base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton; - KeygenHandler handler(768, challenge, GURL("http://www.example.com")); - handler.set_stores_key(false); // Don't leave the key-pair behind. - *result = handler.GenKeyAndSignChallenge(); + handler->set_stores_key(false); // Don't leave the key-pair behind. + *result = handler->GenKeyAndSignChallenge(); event->Signal(); #if defined(USE_NSS) // Detach the thread from NSPR. @@ -110,12 +143,15 @@ TEST_F(KeygenHandlerTest, ConcurrencyTest) { base::WaitableEvent* events[NUM_HANDLERS] = { NULL }; std::string results[NUM_HANDLERS]; for (int i = 0; i < NUM_HANDLERS; i++) { + scoped_ptr<KeygenHandler> handler(CreateKeygenHandler()); events[i] = new base::WaitableEvent(false, false); - base::WorkerPool::PostTask( - FROM_HERE, - base::Bind(ConcurrencyTestCallback, events[i], "some challenge", - &results[i]), - true); + base::WorkerPool::PostTask(FROM_HERE, + base::Bind(ConcurrencyTestCallback, + "some challenge", + events[i], + base::Passed(&handler), + &results[i]), + true); } for (int i = 0; i < NUM_HANDLERS; i++) { diff --git a/chromium/net/base/keygen_handler_win.cc b/chromium/net/base/keygen_handler_win.cc index 59dc69de54c..44365fa136d 100644 --- a/chromium/net/base/keygen_handler_win.cc +++ b/chromium/net/base/keygen_handler_win.cc @@ -5,10 +5,7 @@ #include "net/base/keygen_handler.h" #include <windows.h> -#include <wincrypt.h> -#pragma comment(lib, "crypt32.lib") #include <rpc.h> -#pragma comment(lib, "rpcrt4.lib") #include <list> #include <string> @@ -22,7 +19,10 @@ #include "base/strings/utf_string_conversions.h" #include "crypto/capi_util.h" #include "crypto/scoped_capi_types.h" +#include "crypto/wincrypt_shim.h" +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "rpcrt4.lib") namespace net { @@ -36,7 +36,8 @@ bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) { // as a CERT_PUBLIC_KEY_INFO structure. Currently, only RSA public keys are // supported. ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, - szOID_RSA_RSA, 0, NULL, NULL, &size); + const_cast<char*>(szOID_RSA_RSA), 0, NULL, + NULL, &size); DCHECK(ok); if (!ok) return false; @@ -46,8 +47,8 @@ bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) { PCERT_PUBLIC_KEY_INFO public_key_casted = reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&(*output)[0]); ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING, - szOID_RSA_RSA, 0, NULL, public_key_casted, - &size); + const_cast<char*>(szOID_RSA_RSA), 0, NULL, + public_key_casted, &size); DCHECK(ok); if (!ok) return false; @@ -64,7 +65,7 @@ bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) { bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov, const std::string& challenge, std::string* output) { - std::wstring wide_challenge = base::ASCIIToWide(challenge); + base::string16 challenge16 = base::ASCIIToUTF16(challenge); std::vector<BYTE> spki; if (!GetSubjectPublicKeyInfo(prov, &spki)) @@ -78,11 +79,11 @@ bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov, pkac.dwVersion = CERT_KEYGEN_REQUEST_V1; pkac.SubjectPublicKeyInfo = *reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&spki[0]); - pkac.pwszChallengeString = const_cast<wchar_t*>(wide_challenge.c_str()); + pkac.pwszChallengeString = const_cast<base::char16*>(challenge16.c_str()); CRYPT_ALGORITHM_IDENTIFIER sig_alg; memset(&sig_alg, 0, sizeof(sig_alg)); - sig_alg.pszObjId = szOID_RSA_MD5RSA; + sig_alg.pszObjId = const_cast<char*>(szOID_RSA_MD5RSA); BOOL ok; DWORD size = 0; diff --git a/chromium/net/base/linked_hash_map.h b/chromium/net/base/linked_hash_map.h index 7948647df05..b024ca1d536 100644 --- a/chromium/net/base/linked_hash_map.h +++ b/chromium/net/base/linked_hash_map.h @@ -79,6 +79,28 @@ class linked_hash_map { return list_.rend(); } + // Front and back accessors common to many stl containers. + + // Returns the earliest-inserted element + const value_type& front() const { + return list_.front(); + } + + // Returns the earliest-inserted element. + value_type& front() { + return list_.front(); + } + + // Returns the most-recently-inserted element. + const value_type& back() const { + return list_.back(); + } + + // Returns the most-recently-inserted element. + value_type& back() { + return list_.back(); + } + // Clears the map of all values. void clear() { map_.clear(); diff --git a/chromium/net/base/load_flags_list.h b/chromium/net/base/load_flags_list.h index 2d004886d1c..6e49bbbcc08 100644 --- a/chromium/net/base/load_flags_list.h +++ b/chromium/net/base/load_flags_list.h @@ -38,89 +38,90 @@ LOAD_FLAG(DISABLE_CACHE, 1 << 5) // URLRequest::Interceptors. LOAD_FLAG(DISABLE_INTERCEPT, 1 << 6) -// If present, upload progress messages should be provided to initiator. -LOAD_FLAG(ENABLE_UPLOAD_PROGRESS, 1 << 7) - -// If present, collect load timing for the request. -LOAD_FLAG(ENABLE_LOAD_TIMING, 1 << 8) - // If present, ignores certificate mismatches with the domain name. // (The default behavior is to trigger an OnSSLCertificateError callback.) -LOAD_FLAG(IGNORE_CERT_COMMON_NAME_INVALID, 1 << 9) +LOAD_FLAG(IGNORE_CERT_COMMON_NAME_INVALID, 1 << 7) // If present, ignores certificate expiration dates // (The default behavior is to trigger an OnSSLCertificateError callback). -LOAD_FLAG(IGNORE_CERT_DATE_INVALID, 1 << 10) +LOAD_FLAG(IGNORE_CERT_DATE_INVALID, 1 << 8) // If present, trusts all certificate authorities // (The default behavior is to trigger an OnSSLCertificateError callback). -LOAD_FLAG(IGNORE_CERT_AUTHORITY_INVALID, 1 << 11) +LOAD_FLAG(IGNORE_CERT_AUTHORITY_INVALID, 1 << 9) // If present, causes certificate revocation checks to be skipped on secure // connections. -LOAD_FLAG(DISABLE_CERT_REVOCATION_CHECKING, 1 << 12) +LOAD_FLAG(DISABLE_CERT_REVOCATION_CHECKING, 1 << 10) // If present, ignores wrong key usage of the certificate // (The default behavior is to trigger an OnSSLCertificateError callback). -LOAD_FLAG(IGNORE_CERT_WRONG_USAGE, 1 << 13) +LOAD_FLAG(IGNORE_CERT_WRONG_USAGE, 1 << 11) // This load will not make any changes to cookies, including storing new // cookies or updating existing ones. -LOAD_FLAG(DO_NOT_SAVE_COOKIES, 1 << 14) +LOAD_FLAG(DO_NOT_SAVE_COOKIES, 1 << 12) // Do not resolve proxies. This override is used when downloading PAC files // to avoid having a circular dependency. -LOAD_FLAG(BYPASS_PROXY, 1 << 15) +LOAD_FLAG(BYPASS_PROXY, 1 << 13) // Indicate this request is for a download, as opposed to viewing. -LOAD_FLAG(IS_DOWNLOAD, 1 << 16) +LOAD_FLAG(IS_DOWNLOAD, 1 << 14) // Requires EV certificate verification. -LOAD_FLAG(VERIFY_EV_CERT, 1 << 17) +LOAD_FLAG(VERIFY_EV_CERT, 1 << 15) // This load will not send any cookies. -LOAD_FLAG(DO_NOT_SEND_COOKIES, 1 << 18) +LOAD_FLAG(DO_NOT_SEND_COOKIES, 1 << 16) // This load will not send authentication data (user name/password) // to the server (as opposed to the proxy). -LOAD_FLAG(DO_NOT_SEND_AUTH_DATA, 1 << 19) +LOAD_FLAG(DO_NOT_SEND_AUTH_DATA, 1 << 17) // This should only be used for testing (set by HttpNetworkTransaction). -LOAD_FLAG(IGNORE_ALL_CERT_ERRORS, 1 << 20) +LOAD_FLAG(IGNORE_ALL_CERT_ERRORS, 1 << 18) // Indicate that this is a top level frame, so that we don't assume it is a // subresource and speculatively pre-connect or pre-resolve when a referring // page is loaded. -LOAD_FLAG(MAIN_FRAME, 1 << 21) +LOAD_FLAG(MAIN_FRAME, 1 << 19) // Indicate that this is a sub frame, and hence it might have subresources that // should be speculatively resolved, or even speculatively preconnected. -LOAD_FLAG(SUB_FRAME, 1 << 22) +LOAD_FLAG(SUB_FRAME, 1 << 20) // If present, intercept actual request/response headers from network stack // and report them to renderer. This includes cookies, so the flag is only // respected if renderer has CanReadRawCookies capability in the security // policy. -LOAD_FLAG(REPORT_RAW_HEADERS, 1 << 23) +LOAD_FLAG(REPORT_RAW_HEADERS, 1 << 21) // Indicates that this load was motivated by the rel=prefetch feature, // and is (in theory) not intended for the current frame. -LOAD_FLAG(PREFETCH, 1 << 24) +LOAD_FLAG(PREFETCH, 1 << 22) // Indicates that this is a load that ignores limits and should complete // immediately. -LOAD_FLAG(IGNORE_LIMITS, 1 << 25) +LOAD_FLAG(IGNORE_LIMITS, 1 << 23) // Suppress login prompts for this request. Cached credentials or // default credentials may still be used for authentication. -LOAD_FLAG(DO_NOT_PROMPT_FOR_LOGIN, 1 << 26) +LOAD_FLAG(DO_NOT_PROMPT_FOR_LOGIN, 1 << 24) // Indicates that the operation is somewhat likely to be due to an // explicit user action. This can be used as a hint to treat the // request with higher priority. -LOAD_FLAG(MAYBE_USER_GESTURE, 1 << 27) +LOAD_FLAG(MAYBE_USER_GESTURE, 1 << 25) // Indicates that the username:password portion of the URL should not // be honored, but that other forms of authority may be used. -LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 28) +LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 26) + +// Send request directly to the origin if the effective proxy is the data +// reduction proxy. +// TODO(rcs): Remove this flag as soon as http://crbug.com/339237 is resolved. +LOAD_FLAG(BYPASS_DATA_REDUCTION_PROXY, 1 << 27) +// Indicates the the request is an asynchronous revalidation. +LOAD_FLAG(ASYNC_REVALIDATION, 1 << 28) diff --git a/chromium/net/base/mime_sniffer.cc b/chromium/net/base/mime_sniffer.cc index ef2e27030bb..61ef9482110 100644 --- a/chromium/net/base/mime_sniffer.cc +++ b/chromium/net/base/mime_sniffer.cc @@ -612,12 +612,14 @@ static bool SniffXML(const char* content, if (!pos) return false; - if (base::strncasecmp(pos, "<?xml", sizeof("<?xml") - 1) == 0) { + if ((pos + sizeof("<?xml") - 1 <= end) && + (base::strncasecmp(pos, "<?xml", sizeof("<?xml") - 1) == 0)) { // Skip XML declarations. ++pos; continue; - } else if (base::strncasecmp(pos, "<!DOCTYPE", - sizeof("<!DOCTYPE") - 1) == 0) { + } else if ((pos + sizeof("<!DOCTYPE") - 1 <= end) && + (base::strncasecmp(pos, "<!DOCTYPE", sizeof("<!DOCTYPE") - 1) == + 0)) { // Skip DOCTYPE declarations. ++pos; continue; diff --git a/chromium/net/base/mime_util.cc b/chromium/net/base/mime_util.cc index 9b02c4c18d0..27f3c7049ad 100644 --- a/chromium/net/base/mime_util.cc +++ b/chromium/net/base/mime_util.cc @@ -11,6 +11,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -50,6 +51,25 @@ namespace net { // Singleton utility class for mime types. class MimeUtil : public PlatformMimeUtil { public: + enum Codec { + INVALID_CODEC, + PCM, + MP3, + MPEG2_AAC_LC, + MPEG2_AAC_MAIN, + MPEG2_AAC_SSR, + MPEG4_AAC_LC, + MPEG4_AAC_SBRv1, + VORBIS, + OPUS, + H264_BASELINE, + H264_MAIN, + H264_HIGH, + VP8, + VP9, + THEORA + }; + bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, std::string* mime_type) const; @@ -83,7 +103,7 @@ class MimeUtil : public PlatformMimeUtil { bool strip); bool IsStrictMediaMimeType(const std::string& mime_type) const; - bool IsSupportedStrictMediaMimeType( + SupportsType IsSupportedStrictMediaMimeType( const std::string& mime_type, const std::vector<std::string>& codecs) const; @@ -93,14 +113,27 @@ class MimeUtil : public PlatformMimeUtil { friend struct base::DefaultLazyInstanceTraits<MimeUtil>; typedef base::hash_set<std::string> MimeMappings; - typedef std::map<std::string, MimeMappings> StrictMappings; + + typedef base::hash_set<int> CodecSet; + typedef std::map<std::string, CodecSet> StrictMappings; + struct CodecEntry { + CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} + CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} + Codec codec; + bool is_ambiguous; + }; + typedef std::map<std::string, CodecEntry> StringToCodecMappings; MimeUtil(); - // Returns true if |codecs| is nonempty and all the items in it are present in - // |supported_codecs|. - static bool AreSupportedCodecs(const MimeMappings& supported_codecs, - const std::vector<std::string>& codecs); + // Returns IsSupported if all codec IDs in |codecs| are unambiguous + // and are supported by the platform. MayBeSupported is returned if + // at least one codec ID in |codecs| is ambiguous but all the codecs + // are supported by the platform. IsNotSupported is returned if at + // least one codec ID is not supported by the platform. + SupportsType AreSupportedCodecs( + const CodecSet& supported_codecs, + const std::vector<std::string>& codecs) const; // For faster lookup, keep hash sets. void InitializeMimeTypeMaps(); @@ -109,14 +142,51 @@ class MimeUtil : public PlatformMimeUtil { bool include_platform_types, std::string* mime_type) const; + // Converts a codec ID into an Codec enum value and indicates + // whether the conversion was ambiguous. + // Returns true if this method was able to map |codec_id| to a specific + // Codec enum value. |codec| and |is_ambiguous| are only valid if true + // is returned. Otherwise their value is undefined after the call. + // |is_ambiguous| is true if |codec_id| did not have enough information to + // unambiguously determine the proper Codec enum value. If |is_ambiguous| + // is true |codec| contains the best guess for the intended Codec enum value. + bool StringToCodec(const std::string& codec_id, + Codec* codec, + bool* is_ambiguous) const; + + // Returns true if |codec| is supported by the platform. + // Note: This method will return false if the platform supports proprietary + // codecs but |allow_proprietary_codecs_| is set to false. + bool IsCodecSupported(Codec codec) const; + + // Returns true if |codec| refers to a proprietary codec. + bool IsCodecProprietary(Codec codec) const; + + // Returns true and sets |*default_codec| if |mime_type| has a + // default codec associated with it. + // Returns false otherwise and the value of |*default_codec| is undefined. + bool GetDefaultCodec(const std::string& mime_type, + Codec* default_codec) const; + + // Returns true if |mime_type| has a default codec associated with it + // and IsCodecSupported() returns true for that particular codec. + bool IsDefaultCodecSupported(const std::string& mime_type) const; + MimeMappings image_map_; MimeMappings media_map_; MimeMappings non_image_map_; MimeMappings unsupported_text_map_; MimeMappings javascript_map_; - MimeMappings codecs_map_; + // A map of mime_types and hash map of the supported codecs for the mime_type. StrictMappings strict_format_map_; + + // Keeps track of whether proprietary codec support should be + // advertised to callers. + bool allow_proprietary_codecs_; + + // Lookup table for string compare based string -> Codec mappings. + StringToCodecMappings string_to_codec_map_; }; // class MimeUtil // This variable is Leaky because we need to access it from WorkerPool threads. @@ -173,7 +243,8 @@ static const MimeInfo secondary_mappings[] = { { "application/vnd.mozilla.xul+xml", "xul" }, { "application/x-shockwave-flash", "swf,swl" }, { "application/pkcs7-mime", "p7m,p7c,p7z" }, - { "application/pkcs7-signature", "p7s" } + { "application/pkcs7-signature", "p7s" }, + { "application/x-mpegurl", "m3u8" }, }; static const char* FindMimeType(const MimeInfo* mappings, @@ -308,32 +379,11 @@ static const char* const proprietary_media_types[] = { "audio/mp3", "audio/x-mp3", "audio/mpeg", -}; -// List of supported codecs when passed in with <source type="...">. -// This set of codecs is supported by all variations of Chromium. -// -// Refer to http://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support -// for more information. -// -// The codecs for WAV are integers as defined in Appendix A of RFC2361: -// http://tools.ietf.org/html/rfc2361 -static const char* const common_media_codecs[] = { -#if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. - "theora", +#if defined(ENABLE_MPEG2TS_STREAM_PARSER) + // MPEG-2 TS. + "video/mp2t", #endif - "opus", - "vorbis", - "vp8", - "vp9", - "1" // WAVE_FORMAT_PCM. -}; - -// List of proprietary codecs only supported by Google Chrome. -static const char* const proprietary_media_codecs[] = { - "avc1", - "avc3", - "mp4a" }; // Note: @@ -417,23 +467,42 @@ static const char* const supported_javascript_types[] = { }; #if defined(OS_ANDROID) -static bool IsCodecSupportedOnAndroid(const std::string& codec) { - // Theora is not supported in Android - if (!codec.compare("theora")) - return false; +static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) { + switch (codec) { + case MimeUtil::INVALID_CODEC: + return false; - // VP9 is supported only in KitKat+ (API Level 19). - if ((!codec.compare("vp9") || !codec.compare("vp9.0")) && - base::android::BuildInfo::GetInstance()->sdk_int() < 19) { - return false; - } + case MimeUtil::PCM: + case MimeUtil::MP3: + case MimeUtil::MPEG4_AAC_LC: + case MimeUtil::MPEG4_AAC_SBRv1: + case MimeUtil::H264_BASELINE: + case MimeUtil::H264_MAIN: + case MimeUtil::H264_HIGH: + case MimeUtil::VP8: + case MimeUtil::VORBIS: + return true; - // TODO(vigneshv): Change this similar to the VP9 check once Opus is - // supported on Android (http://crbug.com/318436). - if (!codec.compare("opus")) { - return false; + case MimeUtil::MPEG2_AAC_LC: + case MimeUtil::MPEG2_AAC_MAIN: + case MimeUtil::MPEG2_AAC_SSR: + // MPEG-2 variants of AAC are not supported on Android. + return false; + + case MimeUtil::VP9: + // VP9 is supported only in KitKat+ (API Level 19). + return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; + + case MimeUtil::OPUS: + // TODO(vigneshv): Change this similar to the VP9 check once Opus is + // supported on Android (http://crbug.com/318436). + return false; + + case MimeUtil::THEORA: + return false; } - return true; + + return false; } static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { @@ -452,6 +521,24 @@ struct MediaFormatStrict { const char* codecs_list; }; +// Following is the list of RFC 6381 compliant codecs: +// mp4a.66 - MPEG-2 AAC MAIN +// mp4a.67 - MPEG-2 AAC LC +// mp4a.68 - MPEG-2 AAC SSR +// mp4a.69 - MPEG-2 extension to MPEG-1 +// mp4a.6B - MPEG-1 audio +// mp4a.40.2 - MPEG-4 AAC LC +// mp4a.40.5 - MPEG-4 AAC SBRv1 +// +// avc1.42E0xx - H.264 Baseline +// avc1.4D40xx - H.264 Main +// avc1.6400xx - H.264 High +static const char kMP4AudioCodecsExpression[] = + "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5"; +static const char kMP4VideoCodecsExpression[] = + "avc1.42E00A,avc1.4D400A,avc1.64000A," \ + "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5"; + static const MediaFormatStrict format_codec_mappings[] = { { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" }, { "audio/webm", "opus,vorbis" }, @@ -460,39 +547,82 @@ static const MediaFormatStrict format_codec_mappings[] = { { "video/ogg", "opus,theora,vorbis" }, { "audio/ogg", "opus,vorbis" }, { "application/ogg", "opus,theora,vorbis" }, - { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an - // empty string codec ID and indicates - // a missing codecs= parameter is also valid. - // The presense of 'mp3' is not RFC compliant, - // but is common in the wild so it is a defacto - // standard. + { "audio/mpeg", "mp3" }, { "audio/mp3", "" }, - { "audio/x-mp3", "" } + { "audio/x-mp3", "" }, + { "audio/mp4", kMP4AudioCodecsExpression }, + { "audio/x-m4a", kMP4AudioCodecsExpression }, + { "video/mp4", kMP4VideoCodecsExpression }, + { "video/x-m4v", kMP4VideoCodecsExpression }, + { "application/x-mpegurl", kMP4VideoCodecsExpression }, + { "application/vnd.apple.mpegurl", kMP4VideoCodecsExpression } }; -MimeUtil::MimeUtil() { +struct CodecIDMappings { + const char* const codec_id; + MimeUtil::Codec codec; +}; + +// List of codec IDs that provide enough information to determine the +// codec and profile being requested. +// +// The "mp4a" strings come from RFC 6381. +static const CodecIDMappings kUnambiguousCodecIDs[] = { + { "1", MimeUtil::PCM }, // We only allow this for WAV so it isn't ambiguous. + { "mp3", MimeUtil::MP3 }, + { "mp4a.66", MimeUtil::MPEG2_AAC_MAIN }, + { "mp4a.67", MimeUtil::MPEG2_AAC_LC }, + { "mp4a.68", MimeUtil::MPEG2_AAC_SSR }, + { "mp4a.69", MimeUtil::MP3 }, + { "mp4a.6B", MimeUtil::MP3 }, + { "mp4a.40.2", MimeUtil::MPEG4_AAC_LC }, + { "mp4a.40.5", MimeUtil::MPEG4_AAC_SBRv1 }, + { "vorbis", MimeUtil::VORBIS }, + { "opus", MimeUtil::OPUS }, + { "vp8", MimeUtil::VP8 }, + { "vp8.0", MimeUtil::VP8 }, + { "vp9", MimeUtil::VP9 }, + { "vp9.0", MimeUtil::VP9 }, + { "theora", MimeUtil::THEORA } +}; + +// List of codec IDs that are ambiguous and don't provide +// enough information to determine the codec and profile. +// The codec in these entries indicate the codec and profile +// we assume the user is trying to indicate. +static const CodecIDMappings kAmbiguousCodecIDs[] = { + { "mp4a.40", MimeUtil::MPEG4_AAC_LC }, + { "avc1", MimeUtil::H264_BASELINE }, + { "avc3", MimeUtil::H264_BASELINE }, +}; + +MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { InitializeMimeTypeMaps(); } -// static -bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, - const std::vector<std::string>& codecs) { - if (supported_codecs.empty()) - return codecs.empty(); - - // If no codecs are specified in the mimetype, check to see if a missing - // codecs parameter is allowed. - if (codecs.empty()) - return supported_codecs.find(std::string()) != supported_codecs.end(); +SupportsType MimeUtil::AreSupportedCodecs( + const CodecSet& supported_codecs, + const std::vector<std::string>& codecs) const { + DCHECK(!supported_codecs.empty()); + DCHECK(!codecs.empty()); + SupportsType result = IsSupported; for (size_t i = 0; i < codecs.size(); ++i) { - if (codecs[i].empty() || - supported_codecs.find(codecs[i]) == supported_codecs.end()) { - return false; + bool is_ambiguous = true; + Codec codec = INVALID_CODEC; + if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) + return IsNotSupported; + + if (!IsCodecSupported(codec) || + supported_codecs.find(codec) == supported_codecs.end()) { + return IsNotSupported; } + + if (is_ambiguous) + result = MayBeSupported; } - return true; + return result; } void MimeUtil::InitializeMimeTypeMaps() { @@ -516,6 +646,8 @@ void MimeUtil::InitializeMimeTypeMaps() { non_image_map_.insert(common_media_types[i]); } #if defined(USE_PROPRIETARY_CODECS) + allow_proprietary_codecs_ = true; + for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) non_image_map_.insert(proprietary_media_types[i]); #endif @@ -536,17 +668,15 @@ void MimeUtil::InitializeMimeTypeMaps() { for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) javascript_map_.insert(supported_javascript_types[i]); - for (size_t i = 0; i < arraysize(common_media_codecs); ++i) { -#if defined(OS_ANDROID) - if (!IsCodecSupportedOnAndroid(common_media_codecs[i])) - continue; -#endif - codecs_map_.insert(common_media_codecs[i]); + for (size_t i = 0; i < arraysize(kUnambiguousCodecIDs); ++i) { + string_to_codec_map_[kUnambiguousCodecIDs[i].codec_id] = + CodecEntry(kUnambiguousCodecIDs[i].codec, false); + } + + for (size_t i = 0; i < arraysize(kAmbiguousCodecIDs); ++i) { + string_to_codec_map_[kAmbiguousCodecIDs[i].codec_id] = + CodecEntry(kAmbiguousCodecIDs[i].codec, true); } -#if defined(USE_PROPRIETARY_CODECS) - for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) - codecs_map_.insert(proprietary_media_codecs[i]); -#endif // Initialize the strict supported media types. for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { @@ -555,14 +685,15 @@ void MimeUtil::InitializeMimeTypeMaps() { &mime_type_codecs, false); - MimeMappings codecs; + CodecSet codecs; for (size_t j = 0; j < mime_type_codecs.size(); ++j) { -#if defined(OS_ANDROID) - if (!IsCodecSupportedOnAndroid(mime_type_codecs[j])) - continue; -#endif - codecs.insert(mime_type_codecs[j]); + Codec codec = INVALID_CODEC; + bool is_ambiguous = true; + CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous)); + DCHECK(!is_ambiguous); + codecs.insert(codec); } + strict_format_map_[format_codec_mappings[i].mime_type] = codecs; } } @@ -639,8 +770,8 @@ bool MatchesMimeTypeParameters(const std::string& mime_type_pattern, bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, const std::string& mime_type) const { // Verify caller is passing lowercase strings. - DCHECK_EQ(StringToLowerASCII(mime_type_pattern), mime_type_pattern); - DCHECK_EQ(StringToLowerASCII(mime_type), mime_type); + DCHECK_EQ(base::StringToLowerASCII(mime_type_pattern), mime_type_pattern); + DCHECK_EQ(base::StringToLowerASCII(mime_type), mime_type); if (mime_type_pattern.empty()) return false; @@ -710,7 +841,7 @@ bool MimeUtil::ParseMimeTypeWithoutParameter( } bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const { - std::string lower_type = StringToLowerASCII(type_string); + std::string lower_type = base::StringToLowerASCII(type_string); for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { if (lower_type.compare(legal_top_level_types[i]) == 0) return true; @@ -721,7 +852,15 @@ bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const { bool MimeUtil::AreSupportedMediaCodecs( const std::vector<std::string>& codecs) const { - return AreSupportedCodecs(codecs_map_, codecs); + for (size_t i = 0; i < codecs.size(); ++i) { + Codec codec = INVALID_CODEC; + bool is_ambiguous = true; + if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || + !IsCodecSupported(codec)) { + return false; + } + } + return true; } void MimeUtil::ParseCodecString(const std::string& codecs, @@ -745,17 +884,36 @@ void MimeUtil::ParseCodecString(const std::string& codecs, } bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { - if (strict_format_map_.find(mime_type) == strict_format_map_.end()) - return false; - return true; + return strict_format_map_.find(mime_type) != strict_format_map_.end(); } -bool MimeUtil::IsSupportedStrictMediaMimeType( +SupportsType MimeUtil::IsSupportedStrictMediaMimeType( const std::string& mime_type, const std::vector<std::string>& codecs) const { - StrictMappings::const_iterator it = strict_format_map_.find(mime_type); - return (it != strict_format_map_.end()) && - AreSupportedCodecs(it->second, codecs); + StrictMappings::const_iterator it_strict_map = + strict_format_map_.find(mime_type); + if (it_strict_map == strict_format_map_.end()) + return codecs.empty() ? MayBeSupported : IsNotSupported; + + if (it_strict_map->second.empty()) { + // We get here if the mimetype does not expect a codecs parameter. + return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ? + IsSupported : IsNotSupported; + } + + if (codecs.empty()) { + // We get here if the mimetype expects to get a codecs parameter, + // but didn't get one. If |mime_type| does not have a default codec + // the best we can do is say "maybe" because we don't have enough + // information. + Codec default_codec = INVALID_CODEC; + if (!GetDefaultCodec(mime_type, &default_codec)) + return MayBeSupported; + + return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported; + } + + return AreSupportedCodecs(it_strict_map->second, codecs); } void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { @@ -763,8 +921,165 @@ void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { non_image_map_.erase(proprietary_media_types[i]); media_map_.erase(proprietary_media_types[i]); } - for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) - codecs_map_.erase(proprietary_media_codecs[i]); + allow_proprietary_codecs_ = false; +} + +// Returns true iff |profile_str| conforms to hex string "42y0", where y is one +// of [8..F]. Requiring constraint_set0_flag be set and profile_idc be 0x42 is +// taken from ISO-14496-10 7.3.2.1, 7.4.2.1, and Annex A.2.1. +// +// |profile_str| is the first four characters of the H.264 suffix string +// (ignoring the last 2 characters of the full 6 character suffix that are +// level_idc). From ISO-14496-10 7.3.2.1, it consists of: +// 8 bits: profile_idc: required to be 0x42 here. +// 1 bit: constraint_set0_flag : required to be true here. +// 1 bit: constraint_set1_flag : ignored here. +// 1 bit: constraint_set2_flag : ignored here. +// 1 bit: constraint_set3_flag : ignored here. +// 4 bits: reserved : required to be 0 here. +// +// The spec indicates other ways, not implemented here, that a |profile_str| +// can indicate a baseline conforming decoder is sufficient for decode in Annex +// A.2.1: "[profile_idc not necessarily 0x42] with constraint_set0_flag set and +// in which level_idc and constraint_set3_flag represent a level less than or +// equal to the specified level." +static bool IsValidH264BaselineProfile(const std::string& profile_str) { + uint32 constraint_set_bits; + if (profile_str.size() != 4 || + profile_str[0] != '4' || + profile_str[1] != '2' || + profile_str[3] != '0' || + !base::HexStringToUInt(base::StringPiece(profile_str.c_str() + 2, 1), + &constraint_set_bits)) { + return false; + } + + return constraint_set_bits >= 8; +} + +static bool IsValidH264Level(const std::string& level_str) { + uint32 level; + if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level)) + return false; + + // Valid levels taken from Table A-1 in ISO-14496-10. + // Essentially |level_str| is toHex(10 * level). + return ((level >= 10 && level <= 13) || + (level >= 20 && level <= 22) || + (level >= 30 && level <= 32) || + (level >= 40 && level <= 42) || + (level >= 50 && level <= 51)); +} + +// Handle parsing H.264 codec IDs as outlined in RFC 6381 and ISO-14496-10. +// avc1.42y0xx, y >= 8 - H.264 Baseline +// avc1.4D40xx - H.264 Main +// avc1.6400xx - H.264 High +// +// avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that are trying to +// signal H.264 Baseline. For example, the idc_level, profile_idc and +// constraint_set3_flag pieces may explicitly require decoder to conform to +// baseline profile at the specified level (see Annex A and constraint_set0 in +// ISO-14496-10). +static bool ParseH264CodecID(const std::string& codec_id, + MimeUtil::Codec* codec, + bool* is_ambiguous) { + // Make sure we have avc1.xxxxxx or avc3.xxxxxx + if (codec_id.size() != 11 || + (!StartsWithASCII(codec_id, "avc1.", true) && + !StartsWithASCII(codec_id, "avc3.", true))) { + return false; + } + + std::string profile = StringToUpperASCII(codec_id.substr(5, 4)); + if (IsValidH264BaselineProfile(profile)) { + *codec = MimeUtil::H264_BASELINE; + } else if (profile == "4D40") { + *codec = MimeUtil::H264_MAIN; + } else if (profile == "6400") { + *codec = MimeUtil::H264_HIGH; + } else { + *codec = MimeUtil::H264_BASELINE; + *is_ambiguous = true; + return true; + } + + *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9))); + return true; +} + +bool MimeUtil::StringToCodec(const std::string& codec_id, + Codec* codec, + bool* is_ambiguous) const { + StringToCodecMappings::const_iterator itr = + string_to_codec_map_.find(codec_id); + if (itr != string_to_codec_map_.end()) { + *codec = itr->second.codec; + *is_ambiguous = itr->second.is_ambiguous; + return true; + } + + // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is + // an H.264 codec ID because currently those are the only ones that can't be + // stored in the |string_to_codec_map_| and require parsing. + return ParseH264CodecID(codec_id, codec, is_ambiguous); +} + +bool MimeUtil::IsCodecSupported(Codec codec) const { + DCHECK_NE(codec, INVALID_CODEC); + +#if defined(OS_ANDROID) + if (!IsCodecSupportedOnAndroid(codec)) + return false; +#endif + + return allow_proprietary_codecs_ || !IsCodecProprietary(codec); +} + +bool MimeUtil::IsCodecProprietary(Codec codec) const { + switch (codec) { + case INVALID_CODEC: + case MP3: + case MPEG2_AAC_LC: + case MPEG2_AAC_MAIN: + case MPEG2_AAC_SSR: + case MPEG4_AAC_LC: + case MPEG4_AAC_SBRv1: + case H264_BASELINE: + case H264_MAIN: + case H264_HIGH: + return true; + + case PCM: + case VORBIS: + case OPUS: + case VP8: + case VP9: + case THEORA: + return false; + } + + return true; +} + +bool MimeUtil::GetDefaultCodec(const std::string& mime_type, + Codec* default_codec) const { + if (mime_type == "audio/mpeg" || + mime_type == "audio/mp3" || + mime_type == "audio/x-mp3") { + *default_codec = MimeUtil::MP3; + return true; + } + + return false; +} + + +bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const { + Codec default_codec = Codec::INVALID_CODEC; + if (!GetDefaultCodec(mime_type, &default_codec)) + return false; + return IsCodecSupported(default_codec); } //---------------------------------------------------------------------------- @@ -840,8 +1155,9 @@ bool IsStrictMediaMimeType(const std::string& mime_type) { return g_mime_util.Get().IsStrictMediaMimeType(mime_type); } -bool IsSupportedStrictMediaMimeType(const std::string& mime_type, - const std::vector<std::string>& codecs) { +SupportsType IsSupportedStrictMediaMimeType( + const std::string& mime_type, + const std::vector<std::string>& codecs) { return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); } @@ -993,7 +1309,7 @@ void GetExtensionsForMimeType( if (unsafe_mime_type == "*/*" || unsafe_mime_type == "*") return; - const std::string mime_type = StringToLowerASCII(unsafe_mime_type); + const std::string mime_type = base::StringToLowerASCII(unsafe_mime_type); base::hash_set<base::FilePath::StringType> unique_extensions; if (EndsWith(mime_type, "/*", true)) { diff --git a/chromium/net/base/mime_util.h b/chromium/net/base/mime_util.h index 6c943a7f7da..24dca3def6e 100644 --- a/chromium/net/base/mime_util.h +++ b/chromium/net/base/mime_util.h @@ -94,12 +94,34 @@ NET_EXPORT void ParseCodecString(const std::string& codecs, // certain subset of codecs. NET_EXPORT bool IsStrictMediaMimeType(const std::string& mime_type); -// Check to see if a particular MIME type is in our list which only supports a -// certain subset of codecs. Returns true if and only if all codecs are -// supported for that specific MIME type, false otherwise. If this returns -// false you will still need to check if the media MIME tpyes and codecs are -// supported. -NET_EXPORT bool IsSupportedStrictMediaMimeType( +// Indicates that the MIME type and (possible codec string) are supported by the +// underlying platform. +enum SupportsType { + // The underlying platform is known not to support the given MIME type and + // codec combination. + IsNotSupported, + + // The underlying platform is known to support the given MIME type and codec + // combination. + IsSupported, + + // The underlying platform is unsure whether the given MIME type and codec + // combination can be rendered or not before actually trying to play it. + MayBeSupported +}; + +// Checks the |mime_type| and |codecs| against the MIME types known to support +// only a particular subset of codecs. +// * Returns IsSupported if the |mime_type| is supported and all the codecs +// within the |codecs| are supported for the |mime_type|. +// * Returns MayBeSupported if the |mime_type| is supported and is known to +// support only a subset of codecs, but |codecs| was empty. Also returned if +// all the codecs in |codecs| are supported, but additional codec parameters +// were supplied (such as profile) for which the support cannot be decided. +// * Returns IsNotSupported if either the |mime_type| is not supported or the +// |mime_type| is supported but at least one of the codecs within |codecs| is +// not supported for the |mime_type|. +NET_EXPORT SupportsType IsSupportedStrictMediaMimeType( const std::string& mime_type, const std::vector<std::string>& codecs); @@ -125,10 +147,14 @@ NET_EXPORT void RemoveProprietaryMediaTypesAndCodecsForTests(); NET_EXPORT const std::string GetIANAMediaType(const std::string& mime_type); // A list of supported certificate-related mime types. +// +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net enum CertificateMimeType { -#define CERTIFICATE_MIME_TYPE(name, value) CERTIFICATE_MIME_TYPE_ ## name = value, -#include "net/base/mime_util_certificate_type_list.h" -#undef CERTIFICATE_MIME_TYPE + CERTIFICATE_MIME_TYPE_UNKNOWN, + CERTIFICATE_MIME_TYPE_X509_USER_CERT, + CERTIFICATE_MIME_TYPE_X509_CA_CERT, + CERTIFICATE_MIME_TYPE_PKCS12_ARCHIVE, }; NET_EXPORT CertificateMimeType GetCertificateMimeTypeForMimeType( diff --git a/chromium/net/base/mime_util_certificate_type_list.h b/chromium/net/base/mime_util_certificate_type_list.h deleted file mode 100644 index b7e1be0096c..00000000000 --- a/chromium/net/base/mime_util_certificate_type_list.h +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -// This file intentionally does not have header guards, it's included -// inside a macro to generate enum values. - -// This file contains the list of certificate MIME types. - -CERTIFICATE_MIME_TYPE(UNKNOWN, 0) -CERTIFICATE_MIME_TYPE(X509_USER_CERT, 1) -CERTIFICATE_MIME_TYPE(X509_CA_CERT, 2) -CERTIFICATE_MIME_TYPE(PKCS12_ARCHIVE, 3) diff --git a/chromium/net/base/mime_util_unittest.cc b/chromium/net/base/mime_util_unittest.cc index bb783af90f3..49c46614908 100644 --- a/chromium/net/base/mime_util_unittest.cc +++ b/chromium/net/base/mime_util_unittest.cc @@ -24,13 +24,16 @@ TEST(MimeUtilTest, ExtensionTest) { { FILE_PATH_LITERAL("css"), "text/css", true }, { FILE_PATH_LITERAL("pjp"), "image/jpeg", true }, { FILE_PATH_LITERAL("pjpeg"), "image/jpeg", true }, +#if defined(OS_ANDROID) + { FILE_PATH_LITERAL("m3u8"), "application/x-mpegurl", true }, +#endif { FILE_PATH_LITERAL("not an extension / for sure"), "", false }, }; std::string mime_type; bool rv; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { rv = GetMimeTypeFromExtension(tests[i].extension, &mime_type); EXPECT_EQ(tests[i].valid, rv); if (rv) @@ -55,7 +58,7 @@ TEST(MimeUtilTest, FileTest) { std::string mime_type; bool rv; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { rv = GetMimeTypeFromFile(base::FilePath(tests[i].file_path), &mime_type); EXPECT_EQ(tests[i].valid, rv); @@ -113,15 +116,13 @@ TEST(MimeUtilTest, StrictMediaMimeType) { EXPECT_TRUE(IsStrictMediaMimeType("audio/mp3")); EXPECT_TRUE(IsStrictMediaMimeType("audio/x-mp3")); - // TODO(amogh.bihani): These will be fixed http://crbug.com/53193 - EXPECT_FALSE(IsStrictMediaMimeType("video/mp4")); - EXPECT_FALSE(IsStrictMediaMimeType("video/x-m4v")); - EXPECT_FALSE(IsStrictMediaMimeType("audio/mp4")); - EXPECT_FALSE(IsStrictMediaMimeType("audio/x-m4a")); + EXPECT_TRUE(IsStrictMediaMimeType("video/mp4")); + EXPECT_TRUE(IsStrictMediaMimeType("video/x-m4v")); + EXPECT_TRUE(IsStrictMediaMimeType("audio/mp4")); + EXPECT_TRUE(IsStrictMediaMimeType("audio/x-m4a")); - EXPECT_FALSE(IsStrictMediaMimeType("application/x-mpegurl")); - EXPECT_FALSE(IsStrictMediaMimeType("application/vnd.apple.mpegurl")); - // --------------------------------------------------------------------------- + EXPECT_TRUE(IsStrictMediaMimeType("application/x-mpegurl")); + EXPECT_TRUE(IsStrictMediaMimeType("application/vnd.apple.mpegurl")); EXPECT_FALSE(IsStrictMediaMimeType("video/unknown")); EXPECT_FALSE(IsStrictMediaMimeType("audio/unknown")); @@ -230,6 +231,12 @@ TEST(MimeUtilTest, CommonMediaMimeType) { EXPECT_TRUE(IsSupportedMediaMimeType("audio/mp3")); EXPECT_TRUE(IsSupportedMediaMimeType("audio/x-mp3")); EXPECT_TRUE(IsSupportedMediaMimeType("audio/mpeg")); + +#if defined(ENABLE_MPEG2TS_STREAM_PARSER) + EXPECT_TRUE(IsSupportedMediaMimeType("video/mp2t")); +#else + EXPECT_FALSE(IsSupportedMediaMimeType("video/mp2t")); +#endif #else EXPECT_FALSE(IsSupportedMediaMimeType("audio/mp4")); EXPECT_FALSE(IsSupportedMediaMimeType("audio/x-m4a")); @@ -267,7 +274,7 @@ TEST(MimeUtilTest, ParseCodecString) { { ",", 2, { "", "" } }, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::vector<std::string> codecs_out; ParseCodecString(tests[i].original, &codecs_out, true); ASSERT_EQ(tests[i].expected_size, codecs_out.size()); @@ -394,7 +401,7 @@ TEST(MimeUtilTest, TestGetExtensionsForMimeType) { { "aUDIo/*", 6, "wav" }, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::vector<base::FilePath::StringType> extensions; GetExtensionsForMimeType(tests[i].mime_type, &extensions); ASSERT_TRUE(tests[i].min_expected_size <= extensions.size()); diff --git a/chromium/net/base/mock_file_stream.cc b/chromium/net/base/mock_file_stream.cc index be2dc821527..a34edb218be 100644 --- a/chromium/net/base/mock_file_stream.cc +++ b/chromium/net/base/mock_file_stream.cc @@ -33,7 +33,7 @@ MockFileStream::MockFileStream( MockFileStream::~MockFileStream() { } -int MockFileStream::Seek(Whence whence, int64 offset, +int MockFileStream::Seek(base::File::Whence whence, int64 offset, const Int64CompletionCallback& callback) { Int64CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback64, diff --git a/chromium/net/base/mock_file_stream.h b/chromium/net/base/mock_file_stream.h index c9f07f02487..7b7dea83170 100644 --- a/chromium/net/base/mock_file_stream.h +++ b/chromium/net/base/mock_file_stream.h @@ -25,18 +25,19 @@ class MockFileStream : public net::FileStream { explicit MockFileStream(const scoped_refptr<base::TaskRunner>& task_runner); MockFileStream(base::File file, const scoped_refptr<base::TaskRunner>& task_runner); - virtual ~MockFileStream(); + ~MockFileStream() override; // FileStream methods. - virtual int Seek(net::Whence whence, int64 offset, - const Int64CompletionCallback& callback) OVERRIDE; - virtual int Read(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) OVERRIDE; - virtual int Write(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) OVERRIDE; - virtual int Flush(const CompletionCallback& callback) OVERRIDE; + int Seek(base::File::Whence whence, + int64 offset, + const Int64CompletionCallback& callback) override; + int Read(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) override; + int Write(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) override; + int Flush(const CompletionCallback& callback) override; void set_forced_error_async(int error) { forced_error_ = error; diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h index 65d3a45d198..89fbfff08c1 100644 --- a/chromium/net/base/net_error_list.h +++ b/chromium/net/base/net_error_list.h @@ -96,9 +96,13 @@ NET_ERROR(SOCKET_IS_CONNECTED, -23) // The request was blocked because the forced reenrollment check is still // pending. This error can only occur on ChromeOS. -// The error can be emitted by code in c/b/policy/policy_helpers.cc. +// The error can be emitted by code in chrome/browser/policy/policy_helpers.cc. NET_ERROR(BLOCKED_ENROLLMENT_CHECK_PENDING, -24) +// The upload failed because the upload stream needed to be re-read, due to a +// retry or a redirect, but the upload stream doesn't support that operation. +NET_ERROR(UPLOAD_STREAM_REWIND_NOT_SUPPORTED, -25) + // A connection was closed (corresponding to a TCP FIN). NET_ERROR(CONNECTION_CLOSED, -100) @@ -332,6 +336,14 @@ NET_ERROR(SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE, -162) // return code from setsockopt. NET_ERROR(SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE, -163) +// Failed to import a client certificate from the platform store into the SSL +// library. +NET_ERROR(SSL_CLIENT_AUTH_CERT_BAD_FORMAT, -164) + +// The SSL server requires falling back to a version older than the configured +// minimum fallback version, and thus fallback failed. +NET_ERROR(SSL_FALLBACK_BEYOND_MINIMUM_VERSION, -165) + // Certificate error codes // // The values of certificate error codes must be consecutive. @@ -645,6 +657,9 @@ NET_ERROR(CACHE_CHECKSUM_READ_FAILURE, -407) // SimpleCache backend, but not by any URLRequest methods or members. NET_ERROR(CACHE_CHECKSUM_MISMATCH, -408) +// Internal error code for the HTTP cache. The cache lock timeout has fired. +NET_ERROR(CACHE_LOCK_TIMEOUT, -409) + // The server's response was insecure (e.g. there was a cert error). NET_ERROR(INSECURE_RESPONSE, -501) @@ -732,6 +747,9 @@ NET_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713) // The certificate database changed in some way. NET_ERROR(CERT_DATABASE_CHANGED, -714) +// Failure to import Channel ID. +NET_ERROR(CHANNEL_ID_IMPORT_FAILED, -715) + // DNS error codes. // DNS resolver received a malformed response. diff --git a/chromium/net/base/net_errors.cc b/chromium/net/base/net_errors.cc index a9d1443c913..55cdebb1ac5 100644 --- a/chromium/net/base/net_errors.cc +++ b/chromium/net/base/net_errors.cc @@ -24,18 +24,47 @@ namespace net { const char kErrorDomain[] = "net"; -const char* ErrorToString(int error) { +std::string ErrorToString(int error) { + return "net::" + ErrorToShortString(error); +} + +std::string ErrorToShortString(int error) { if (error == 0) - return "net::OK"; + return "OK"; + const char* error_string; switch (error) { #define NET_ERROR(label, value) \ case ERR_ ## label: \ - return "net::" STRINGIZE_NO_EXPANSION(ERR_ ## label); + error_string = # label; \ + break; #include "net/base/net_error_list.h" #undef NET_ERROR default: - return "net::<unknown>"; + NOTREACHED(); + error_string = "<unknown>"; + } + return std::string("ERR_") + error_string; +} + +bool IsCertificateError(int error) { + // Certificate errors are negative integers from net::ERR_CERT_BEGIN + // (inclusive) to net::ERR_CERT_END (exclusive) in *decreasing* order. + // ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN is currently an exception to this + // rule. + return (error <= ERR_CERT_BEGIN && error > ERR_CERT_END) || + (error == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN); +} + +bool IsClientCertificateError(int error) { + switch (error) { + case ERR_BAD_SSL_CLIENT_AUTH_CERT: + case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED: + case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY: + case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED: + return true; + default: + return false; } } diff --git a/chromium/net/base/net_errors.h b/chromium/net/base/net_errors.h index 2c513612209..29b7742f721 100644 --- a/chromium/net/base/net_errors.h +++ b/chromium/net/base/net_errors.h @@ -5,6 +5,7 @@ #ifndef NET_BASE_NET_ERRORS_H__ #define NET_BASE_NET_ERRORS_H__ +#include <string> #include <vector> #include "base/basictypes.h" @@ -30,17 +31,18 @@ enum Error { }; // Returns a textual representation of the error code for logging purposes. -NET_EXPORT const char* ErrorToString(int error); +NET_EXPORT std::string ErrorToString(int error); + +// Same as above, but leaves off the leading "net::". +NET_EXPORT std::string ErrorToShortString(int error); // Returns true if |error| is a certificate error code. -inline bool IsCertificateError(int error) { - // Certificate errors are negative integers from net::ERR_CERT_BEGIN - // (inclusive) to net::ERR_CERT_END (exclusive) in *decreasing* order. - // ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN is currently an exception to this - // rule. - return (error <= ERR_CERT_BEGIN && error > ERR_CERT_END) || - (error == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN); -} +NET_EXPORT bool IsCertificateError(int error); + +// Returns true if |error| is a client certificate authentication error. This +// does not include ERR_SSL_PROTOCOL_ERROR which may also signal a bad client +// certificate. +NET_EXPORT bool IsClientCertificateError(int error); // Map system error code to Error. NET_EXPORT Error MapSystemError(int os_error); diff --git a/chromium/net/base/net_info_source_list.h b/chromium/net/base/net_info_source_list.h new file mode 100644 index 00000000000..be3019e9183 --- /dev/null +++ b/chromium/net/base/net_info_source_list.h @@ -0,0 +1,22 @@ +// Copyright 2014 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. + +// This file intentionally does not have header guards, it's included +// inside a macro to generate enum values. + +// Flags used to request different types of information about the current state +// of a URLRequestContext. +// +// The strings don't match the enums for historical reasons. + +NET_INFO_SOURCE(PROXY_SETTINGS, "proxySettings", 1 << 0) +NET_INFO_SOURCE(BAD_PROXIES, "badProxies", 1 << 1) +NET_INFO_SOURCE(HOST_RESOLVER, "hostResolverInfo", 1 << 2) +NET_INFO_SOURCE(SOCKET_POOL, "socketPoolInfo", 1 << 3) +NET_INFO_SOURCE(QUIC, "quicInfo", 1 << 4) +NET_INFO_SOURCE(SPDY_SESSIONS, "spdySessionInfo", 1 << 5) +NET_INFO_SOURCE(SPDY_STATUS, "spdyStatus", 1 << 6) +NET_INFO_SOURCE(SPDY_ALT_PROTO_MAPPINGS, "spdyAlternateProtocolMappings", + 1 << 7) +NET_INFO_SOURCE(HTTP_CACHE, "httpCacheInfo", 1 << 8) diff --git a/chromium/net/base/net_log.cc b/chromium/net/base/net_log.cc index 6016d0de026..4f460356399 100644 --- a/chromium/net/base/net_log.cc +++ b/chromium/net/base/net_log.cc @@ -101,10 +101,10 @@ NetLog::ParametersCallback NetLog::Source::ToEventParametersCallback() const { // static bool NetLog::Source::FromEventParameters(base::Value* event_params, Source* source) { - base::DictionaryValue* dict; - base::DictionaryValue* source_dict; - int source_id; - int source_type; + base::DictionaryValue* dict = NULL; + base::DictionaryValue* source_dict = NULL; + int source_id = -1; + int source_type = NetLog::SOURCE_COUNT; if (!event_params || !event_params->GetAsDictionary(&dict) || !dict->GetDictionary("source_dependency", &source_dict) || @@ -114,7 +114,7 @@ bool NetLog::Source::FromEventParameters(base::Value* event_params, return false; } - DCHECK_LE(0, source_id); + DCHECK_GE(source_id, 0); DCHECK_LT(source_type, NetLog::SOURCE_COUNT); *source = Source(static_cast<SourceType>(source_type), source_id); return true; @@ -198,10 +198,7 @@ void NetLog::ThreadSafeObserver::OnAddEntryData(const EntryData& entry_data) { OnAddEntry(Entry(&entry_data, log_level())); } -NetLog::NetLog() - : last_id_(0), - base_log_level_(LOG_NONE), - effective_log_level_(LOG_NONE) { +NetLog::NetLog() : last_id_(0), effective_log_level_(LOG_NONE) { } NetLog::~NetLog() { @@ -227,13 +224,6 @@ uint32 NetLog::NextID() { return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1); } -void NetLog::SetBaseLogLevel(LogLevel log_level) { - base::AutoLock lock(lock_); - base_log_level_ = log_level; - - UpdateLogLevel(); -} - NetLog::LogLevel NetLog::GetLogLevel() const { base::subtle::Atomic32 log_level = base::subtle::NoBarrier_Load(&effective_log_level_); @@ -285,7 +275,7 @@ void NetLog::UpdateLogLevel() { // Look through all the observers and find the finest granularity // log level (higher values of the enum imply *lower* log levels). - LogLevel new_effective_log_level = base_log_level_; + LogLevel new_effective_log_level = LOG_NONE; ObserverListBase<ThreadSafeObserver>::Iterator it(observers_); ThreadSafeObserver* observer; while ((observer = it.GetNext()) != NULL) { diff --git a/chromium/net/base/net_log.h b/chromium/net/base/net_log.h index b037a336bc5..1b598ed84b7 100644 --- a/chromium/net/base/net_log.h +++ b/chromium/net/base/net_log.h @@ -300,10 +300,6 @@ class NET_EXPORT NetLog { static ParametersCallback StringCallback(const char* name, const base::string16* value); - protected: - // Set the lowest allowed log level, regardless of any Observers. - void SetBaseLogLevel(LogLevel log_level); - private: friend class BoundNetLog; @@ -322,10 +318,6 @@ class NET_EXPORT NetLog { // Last assigned source ID. Incremented to get the next one. base::subtle::Atomic32 last_id_; - // The lowest allowed log level, regardless of any Observers. - // Normally defaults to LOG_NONE, but can be changed with SetBaseLogLevel - LogLevel base_log_level_; - // The current log level. base::subtle::Atomic32 effective_log_level_; diff --git a/chromium/net/base/net_log_event_type_list.h b/chromium/net/base/net_log_event_type_list.h index c6ed7c5d937..823cde18bd3 100644 --- a/chromium/net/base/net_log_event_type_list.h +++ b/chromium/net/base/net_log_event_type_list.h @@ -798,6 +798,14 @@ EVENT_TYPE(URL_REQUEST_REDIRECT_JOB) // "reason": <Reason for the redirect, as a string>, // } +EVENT_TYPE(URL_REQUEST_FAKE_RESPONSE_HEADERS_CREATED) +// This event is logged when a URLRequestRedirectJob creates the fake response +// headers for a request, prior to returning them. +// The following parameters are attached: +// { +// "headers": <The list of header:value pairs>, +// } + // ------------------------------------------------------------------------ // HttpCache // ------------------------------------------------------------------------ @@ -827,6 +835,29 @@ EVENT_TYPE(HTTP_CACHE_WRITE_INFO) EVENT_TYPE(HTTP_CACHE_READ_DATA) EVENT_TYPE(HTTP_CACHE_WRITE_DATA) +// Identifies the NetLog::Source() for the asynchronous HttpCache::Transaction +// that will revalidate this entry. +// The event parameters are: +// { +// "source_dependency": <Source identifier for the async Transaction> +// } +EVENT_TYPE(HTTP_CACHE_VALIDATE_RESOURCE_ASYNC) + +// The start/end of performing an async revalidation. +// For the BEGIN phase, the event parameters are: +// { +// "source_dependency": <Source identifier for the Request> +// "url": <String of URL being loaded>, +// "method": <Method of request> +// } +// +// For the END phase, if there was an error, the following parameters are +// attached: +// { +// "net_error": <Net error code of the failure>, +// } +EVENT_TYPE(ASYNC_REVALIDATION) + // ------------------------------------------------------------------------ // Disk Cache / Memory Cache // ------------------------------------------------------------------------ @@ -1351,6 +1382,12 @@ EVENT_TYPE(QUIC_SESSION) // } EVENT_TYPE(QUIC_SESSION_CLOSE_ON_ERROR) +// Session verified a certificate from the server. +// { +// "subjects": <list of DNS names that the certificate is valid for>, +// } +EVENT_TYPE(QUIC_SESSION_CERTIFICATE_VERIFIED) + // Session received a QUIC packet. // { // "peer_address": <The ip:port of the peer>, diff --git a/chromium/net/base/net_log_logger.cc b/chromium/net/base/net_log_logger.cc index aa5ec4021f8..bb0331badef 100644 --- a/chromium/net/base/net_log_logger.cc +++ b/chromium/net/base/net_log_logger.cc @@ -9,21 +9,15 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" #include "base/values.h" -#include "net/base/address_family.h" -#include "net/base/load_states.h" -#include "net/quic/quic_protocol.h" -#include "net/quic/quic_utils.h" +#include "net/base/net_log_util.h" namespace net { -// This should be incremented when significant changes are made that will -// invalidate the old loading code. -static const int kLogFormatVersion = 1; - NetLogLogger::NetLogLogger(FILE* file, const base::Value& constants) - : file_(file), log_level_(NetLog::LOG_ALL_BUT_BYTES), added_events_(false) { + : file_(file), + log_level_(NetLog::LOG_STRIP_PRIVATE_DATA), + added_events_(false) { DCHECK(file); // Write constants to the output file. This allows loading files that have @@ -66,170 +60,9 @@ void NetLogLogger::OnAddEntry(const net::NetLog::Entry& entry) { added_events_ = true; } +// static base::DictionaryValue* NetLogLogger::GetConstants() { - base::DictionaryValue* constants_dict = new base::DictionaryValue(); - - // Version of the file format. - constants_dict->SetInteger("logFormatVersion", kLogFormatVersion); - - // Add a dictionary with information on the relationship between event type - // enums and their symbolic names. - constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue()); - - // Add a dictionary with information about the relationship between CertStatus - // flags and their symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - -#define CERT_STATUS_FLAG(label, value) dict->SetInteger(#label, value); -#include "net/cert/cert_status_flags_list.h" -#undef CERT_STATUS_FLAG - - constants_dict->Set("certStatusFlag", dict); - } - - // Add a dictionary with information about the relationship between load flag - // enums and their symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - -#define LOAD_FLAG(label, value) \ - dict->SetInteger(# label, static_cast<int>(value)); -#include "net/base/load_flags_list.h" -#undef LOAD_FLAG - - constants_dict->Set("loadFlag", dict); - } - - // Add a dictionary with information about the relationship between load state - // enums and their symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - -#define LOAD_STATE(label) \ - dict->SetInteger(# label, net::LOAD_STATE_ ## label); -#include "net/base/load_states_list.h" -#undef LOAD_STATE - - constants_dict->Set("loadState", dict); - } - - // Add information on the relationship between net error codes and their - // symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - -#define NET_ERROR(label, value) \ - dict->SetInteger(# label, static_cast<int>(value)); -#include "net/base/net_error_list.h" -#undef NET_ERROR - - constants_dict->Set("netError", dict); - } - - // Add information on the relationship between QUIC error codes and their - // symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - - for (net::QuicErrorCode error = net::QUIC_NO_ERROR; - error < net::QUIC_LAST_ERROR; - error = static_cast<net::QuicErrorCode>(error + 1)) { - dict->SetInteger(net::QuicUtils::ErrorToString(error), - static_cast<int>(error)); - } - - constants_dict->Set("quicError", dict); - } - - // Add information on the relationship between QUIC RST_STREAM error codes - // and their symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - - for (net::QuicRstStreamErrorCode error = net::QUIC_STREAM_NO_ERROR; - error < net::QUIC_STREAM_LAST_ERROR; - error = static_cast<net::QuicRstStreamErrorCode>(error + 1)) { - dict->SetInteger(net::QuicUtils::StreamErrorToString(error), - static_cast<int>(error)); - } - - constants_dict->Set("quicRstStreamError", dict); - } - - // Information about the relationship between event phase enums and their - // symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - - dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN); - dict->SetInteger("PHASE_END", net::NetLog::PHASE_END); - dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE); - - constants_dict->Set("logEventPhase", dict); - } - - // Information about the relationship between source type enums and - // their symbolic names. - constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue()); - - // Information about the relationship between LogLevel enums and their - // symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - - dict->SetInteger("LOG_ALL", net::NetLog::LOG_ALL); - dict->SetInteger("LOG_ALL_BUT_BYTES", net::NetLog::LOG_ALL_BUT_BYTES); - dict->SetInteger("LOG_STRIP_PRIVATE_DATA", - net::NetLog::LOG_STRIP_PRIVATE_DATA); - - constants_dict->Set("logLevelType", dict); - } - - // Information about the relationship between address family enums and - // their symbolic names. - { - base::DictionaryValue* dict = new base::DictionaryValue(); - - dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED", - net::ADDRESS_FAMILY_UNSPECIFIED); - dict->SetInteger("ADDRESS_FAMILY_IPV4", - net::ADDRESS_FAMILY_IPV4); - dict->SetInteger("ADDRESS_FAMILY_IPV6", - net::ADDRESS_FAMILY_IPV6); - - constants_dict->Set("addressFamily", dict); - } - - // Information about how the "time ticks" values we have given it relate to - // actual system times. (We used time ticks throughout since they are stable - // across system clock changes). - { - int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds(); - - int64 cur_time_ticks_ms = - (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds(); - - // If we add this number to a time tick value, it gives the timestamp. - int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms; - - // Chrome on all platforms stores times using the Windows epoch - // (Jan 1 1601), but the javascript wants a unix epoch. - // TODO(eroman): Getting the timestamp relative to the unix epoch should - // be part of the time library. - const int64 kUnixEpochMs = 11644473600000LL; - int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs; - - // Pass it as a string, since it may be too large to fit in an integer. - constants_dict->SetString("timeTickOffset", - base::Int64ToString(tick_to_unix_time_ms)); - } - - // "clientInfo" key is required for some NetLogLogger log readers. - // Provide a default empty value for compatibility. - constants_dict->Set("clientInfo", new base::DictionaryValue()); - - return constants_dict; + return GetNetConstants().release(); } } // namespace net diff --git a/chromium/net/base/net_log_logger.h b/chromium/net/base/net_log_logger.h index 3d53f3910d9..ede3ca443db 100644 --- a/chromium/net/base/net_log_logger.h +++ b/chromium/net/base/net_log_logger.h @@ -8,9 +8,11 @@ #include <stdio.h> #include "base/files/scoped_file.h" +#include "base/macros.h" #include "net/base/net_log.h" namespace base { +class DictionaryValue; class FilePath; class Value; } @@ -27,7 +29,7 @@ class NET_EXPORT NetLogLogger : public NetLog::ThreadSafeObserver { // starts. |file| must be non-NULL handle and be open for writing. // |constants| is a legend for decoding constant values used in the log. NetLogLogger(FILE* file, const base::Value& constants); - virtual ~NetLogLogger(); + ~NetLogLogger() override; // Sets the log level to log at. Must be called before StartObserving. void set_log_level(NetLog::LogLevel log_level); @@ -40,10 +42,13 @@ class NET_EXPORT NetLogLogger : public NetLog::ThreadSafeObserver { void StopObserving(); // net::NetLog::ThreadSafeObserver implementation: - virtual void OnAddEntry(const NetLog::Entry& entry) OVERRIDE; + void OnAddEntry(const NetLog::Entry& entry) override; // Create a dictionary containing legend for net/ constants. Caller takes // ownership of returned value. + // TODO(mmenke): Get rid of this, and have embedders use GetNetConstants + // directly. Also maybe call that function by default, so only embedders + // that need more constants need to worry about it. static base::DictionaryValue* GetConstants(); private: diff --git a/chromium/net/base/net_log_logger_unittest.cc b/chromium/net/base/net_log_logger_unittest.cc index 5d587dabd5f..256ae591740 100644 --- a/chromium/net/base/net_log_logger_unittest.cc +++ b/chromium/net/base/net_log_logger_unittest.cc @@ -4,18 +4,22 @@ #include "net/base/net_log_logger.h" -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/json/json_reader.h" #include "base/values.h" +#include "net/base/net_log.h" +#include "net/base/net_log_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { +namespace { + class NetLogLoggerTest : public testing::Test { public: - virtual void SetUp() { + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); log_path_ = temp_dir_.path().AppendASCII("NetLogFile"); } @@ -26,13 +30,12 @@ class NetLogLoggerTest : public testing::Test { }; TEST_F(NetLogLoggerTest, GeneratesValidJSONForNoEvents) { - { - // Create and destroy a logger. - FILE* file = base::OpenFile(log_path_, "w"); - ASSERT_TRUE(file); - scoped_ptr<base::Value> constants(NetLogLogger::GetConstants()); - NetLogLogger logger(file, *constants); - } + // Create and destroy a logger. + FILE* file = base::OpenFile(log_path_, "w"); + ASSERT_TRUE(file); + scoped_ptr<base::Value> constants(GetNetConstants()); + scoped_ptr<NetLogLogger> logger(new NetLogLogger(file, *constants)); + logger.reset(); std::string input; ASSERT_TRUE(base::ReadFileToString(log_path_, &input)); @@ -48,23 +51,42 @@ TEST_F(NetLogLoggerTest, GeneratesValidJSONForNoEvents) { ASSERT_EQ(0u, events->GetSize()); } +// Make sure the log level is LOG_STRIP_PRIVATE_DATA by default. +TEST_F(NetLogLoggerTest, LogLevel) { + FILE* file = base::OpenFile(log_path_, "w"); + ASSERT_TRUE(file); + scoped_ptr<base::Value> constants(GetNetConstants()); + NetLogLogger logger(file, *constants); + + NetLog net_log; + logger.StartObserving(&net_log); + EXPECT_EQ(NetLog::LOG_STRIP_PRIVATE_DATA, logger.log_level()); + EXPECT_EQ(NetLog::LOG_STRIP_PRIVATE_DATA, net_log.GetLogLevel()); + logger.StopObserving(); + + logger.set_log_level(NetLog::LOG_ALL_BUT_BYTES); + logger.StartObserving(&net_log); + EXPECT_EQ(NetLog::LOG_ALL_BUT_BYTES, logger.log_level()); + EXPECT_EQ(NetLog::LOG_ALL_BUT_BYTES, net_log.GetLogLevel()); + logger.StopObserving(); +} + TEST_F(NetLogLoggerTest, GeneratesValidJSONWithOneEvent) { - { - FILE* file = base::OpenFile(log_path_, "w"); - ASSERT_TRUE(file); - scoped_ptr<base::Value> constants(NetLogLogger::GetConstants()); - NetLogLogger logger(file, *constants); - - const int kDummyId = 1; - NetLog::Source source(NetLog::SOURCE_SPDY_SESSION, kDummyId); - NetLog::EntryData entry_data(NetLog::TYPE_PROXY_SERVICE, - source, - NetLog::PHASE_BEGIN, - base::TimeTicks::Now(), - NULL); - NetLog::Entry entry(&entry_data, NetLog::LOG_ALL); - logger.OnAddEntry(entry); - } + FILE* file = base::OpenFile(log_path_, "w"); + ASSERT_TRUE(file); + scoped_ptr<base::Value> constants(GetNetConstants()); + scoped_ptr<NetLogLogger> logger(new NetLogLogger(file, *constants)); + + const int kDummyId = 1; + NetLog::Source source(NetLog::SOURCE_SPDY_SESSION, kDummyId); + NetLog::EntryData entry_data(NetLog::TYPE_PROXY_SERVICE, + source, + NetLog::PHASE_BEGIN, + base::TimeTicks::Now(), + NULL); + NetLog::Entry entry(&entry_data, NetLog::LOG_ALL); + logger->OnAddEntry(entry); + logger.reset(); std::string input; ASSERT_TRUE(base::ReadFileToString(log_path_, &input)); @@ -81,25 +103,24 @@ TEST_F(NetLogLoggerTest, GeneratesValidJSONWithOneEvent) { } TEST_F(NetLogLoggerTest, GeneratesValidJSONWithMultipleEvents) { - { - FILE* file = base::OpenFile(log_path_, "w"); - ASSERT_TRUE(file); - scoped_ptr<base::Value> constants(NetLogLogger::GetConstants()); - NetLogLogger logger(file, *constants); - - const int kDummyId = 1; - NetLog::Source source(NetLog::SOURCE_SPDY_SESSION, kDummyId); - NetLog::EntryData entry_data(NetLog::TYPE_PROXY_SERVICE, - source, - NetLog::PHASE_BEGIN, - base::TimeTicks::Now(), - NULL); - NetLog::Entry entry(&entry_data, NetLog::LOG_ALL); - - // Add the entry multiple times. - logger.OnAddEntry(entry); - logger.OnAddEntry(entry); - } + FILE* file = base::OpenFile(log_path_, "w"); + ASSERT_TRUE(file); + scoped_ptr<base::Value> constants(GetNetConstants()); + scoped_ptr<NetLogLogger> logger(new NetLogLogger(file, *constants)); + + const int kDummyId = 1; + NetLog::Source source(NetLog::SOURCE_SPDY_SESSION, kDummyId); + NetLog::EntryData entry_data(NetLog::TYPE_PROXY_SERVICE, + source, + NetLog::PHASE_BEGIN, + base::TimeTicks::Now(), + NULL); + NetLog::Entry entry(&entry_data, NetLog::LOG_ALL); + + // Add the entry multiple times. + logger->OnAddEntry(entry); + logger->OnAddEntry(entry); + logger.reset(); std::string input; ASSERT_TRUE(base::ReadFileToString(log_path_, &input)); @@ -115,4 +136,6 @@ TEST_F(NetLogLoggerTest, GeneratesValidJSONWithMultipleEvents) { ASSERT_EQ(2u, events->GetSize()); } +} // namespace + } // namespace net diff --git a/chromium/net/base/net_log_source_type_list.h b/chromium/net/base/net_log_source_type_list.h index 265ba747459..9d66c175f2d 100644 --- a/chromium/net/base/net_log_source_type_list.h +++ b/chromium/net/base/net_log_source_type_list.h @@ -28,3 +28,4 @@ SOURCE_TYPE(FILESTREAM) SOURCE_TYPE(DNS_PROBER) SOURCE_TYPE(PROXY_CLIENT_SOCKET) SOURCE_TYPE(IPV6_REACHABILITY_CHECK) +SOURCE_TYPE(ASYNC_REVALIDATION) diff --git a/chromium/net/base/net_log_unittest.cc b/chromium/net/base/net_log_unittest.cc index 8f15e9cdf7a..0f5b0ebf46c 100644 --- a/chromium/net/base/net_log_unittest.cc +++ b/chromium/net/base/net_log_unittest.cc @@ -75,14 +75,12 @@ class CountingObserver : public NetLog::ThreadSafeObserver { public: CountingObserver() : count_(0) {} - virtual ~CountingObserver() { + ~CountingObserver() override { if (net_log()) net_log()->RemoveThreadSafeObserver(this); } - virtual void OnAddEntry(const NetLog::Entry& entry) OVERRIDE { - ++count_; - } + void OnAddEntry(const NetLog::Entry& entry) override { ++count_; } int count() const { return count_; } @@ -94,12 +92,12 @@ class LoggingObserver : public NetLog::ThreadSafeObserver { public: LoggingObserver() {} - virtual ~LoggingObserver() { + ~LoggingObserver() override { if (net_log()) net_log()->RemoveThreadSafeObserver(this); } - virtual void OnAddEntry(const NetLog::Entry& entry) OVERRIDE { + void OnAddEntry(const NetLog::Entry& entry) override { base::Value* value = entry.ToValue(); base::DictionaryValue* dict = NULL; ASSERT_TRUE(value->GetAsDictionary(&dict)); @@ -138,7 +136,7 @@ class NetLogTestThread : public base::SimpleThread { net_log_ = net_log; } - virtual void Run() OVERRIDE { + void Run() override { start_event_->Wait(); RunTestThread(); } @@ -162,10 +160,10 @@ class NetLogTestThread : public base::SimpleThread { class AddEventsTestThread : public NetLogTestThread { public: AddEventsTestThread() {} - virtual ~AddEventsTestThread() {} + ~AddEventsTestThread() override {} private: - virtual void RunTestThread() OVERRIDE { + void RunTestThread() override { for (int i = 0; i < kEvents; ++i) AddEvent(net_log_); } @@ -178,12 +176,10 @@ class AddRemoveObserverTestThread : public NetLogTestThread { public: AddRemoveObserverTestThread() {} - virtual ~AddRemoveObserverTestThread() { - EXPECT_TRUE(!observer_.net_log()); - } + ~AddRemoveObserverTestThread() override { EXPECT_TRUE(!observer_.net_log()); } private: - virtual void RunTestThread() OVERRIDE { + void RunTestThread() override { for (int i = 0; i < kEvents; ++i) { ASSERT_FALSE(observer_.net_log()); diff --git a/chromium/net/base/net_log_util.cc b/chromium/net/base/net_log_util.cc new file mode 100644 index 00000000000..b8816bad919 --- /dev/null +++ b/chromium/net/base/net_log_util.cc @@ -0,0 +1,461 @@ +// Copyright 2014 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 "net/base/net_log_util.h" + +#include <string> + +#include "base/metrics/field_trial.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "net/base/address_family.h" +#include "net/base/load_states.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/disk_cache/disk_cache.h" +#include "net/dns/host_cache.h" +#include "net/dns/host_resolver.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties.h" +#include "net/http/http_transaction_factory.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_retry_info.h" +#include "net/proxy/proxy_service.h" +#include "net/quic/quic_protocol.h" +#include "net/quic/quic_utils.h" +#include "net/url_request/url_request_context.h" + +namespace net { + +namespace { + +// This should be incremented when significant changes are made that will +// invalidate the old loading code. +const int kLogFormatVersion = 1; + +struct StringToConstant { + const char* name; + const int constant; +}; + +const StringToConstant kCertStatusFlags[] = { +#define CERT_STATUS_FLAG(label, value) { #label, value }, +#include "net/cert/cert_status_flags_list.h" +#undef CERT_STATUS_FLAG +}; + +const StringToConstant kLoadFlags[] = { +#define LOAD_FLAG(label, value) { #label, value }, +#include "net/base/load_flags_list.h" +#undef LOAD_FLAG +}; + +const StringToConstant kLoadStateTable[] = { +#define LOAD_STATE(label) { # label, net::LOAD_STATE_ ## label }, +#include "net/base/load_states_list.h" +#undef LOAD_STATE +}; + +const short kNetErrors[] = { +#define NET_ERROR(label, value) value, +#include "net/base/net_error_list.h" +#undef NET_ERROR +}; + +const char* NetInfoSourceToString(NetInfoSource source) { + switch (source) { + #define NET_INFO_SOURCE(label, string, value) \ + case NET_INFO_ ## label: \ + return string; +#include "net/base/net_info_source_list.h" + #undef NET_INFO_SOURCE + case NET_INFO_ALL_SOURCES: + return "All"; + } + return "?"; +} + +// Returns the disk cache backend for |context| if there is one, or NULL. +// Despite the name, can return an in memory "disk cache". +disk_cache::Backend* GetDiskCacheBackend(net::URLRequestContext* context) { + if (!context->http_transaction_factory()) + return NULL; + + net::HttpCache* http_cache = context->http_transaction_factory()->GetCache(); + if (!http_cache) + return NULL; + + return http_cache->GetCurrentBackend(); +} + +} // namespace + +scoped_ptr<base::DictionaryValue> GetNetConstants() { + scoped_ptr<base::DictionaryValue> constants_dict(new base::DictionaryValue()); + + // Version of the file format. + constants_dict->SetInteger("logFormatVersion", kLogFormatVersion); + + // Add a dictionary with information on the relationship between event type + // enums and their symbolic names. + constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue()); + + // Add a dictionary with information about the relationship between CertStatus + // flags and their symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (size_t i = 0; i < arraysize(kCertStatusFlags); i++) + dict->SetInteger(kCertStatusFlags[i].name, kCertStatusFlags[i].constant); + + constants_dict->Set("certStatusFlag", dict); + } + + // Add a dictionary with information about the relationship between load flag + // enums and their symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (size_t i = 0; i < arraysize(kLoadFlags); i++) + dict->SetInteger(kLoadFlags[i].name, kLoadFlags[i].constant); + + constants_dict->Set("loadFlag", dict); + } + + // Add a dictionary with information about the relationship between load state + // enums and their symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (size_t i = 0; i < arraysize(kLoadStateTable); i++) + dict->SetInteger(kLoadStateTable[i].name, kLoadStateTable[i].constant); + + constants_dict->Set("loadState", dict); + } + + { + base::DictionaryValue* dict = new base::DictionaryValue(); + #define NET_INFO_SOURCE(label, string, value) \ + dict->SetInteger(string, NET_INFO_ ## label); +#include "net/base/net_info_source_list.h" + #undef NET_INFO_SOURCE + constants_dict->Set("netInfoSources", dict); + } + + // Add information on the relationship between net error codes and their + // symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (size_t i = 0; i < arraysize(kNetErrors); i++) + dict->SetInteger(ErrorToShortString(kNetErrors[i]), kNetErrors[i]); + + constants_dict->Set("netError", dict); + } + + // Add information on the relationship between QUIC error codes and their + // symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (net::QuicErrorCode error = net::QUIC_NO_ERROR; + error < net::QUIC_LAST_ERROR; + error = static_cast<net::QuicErrorCode>(error + 1)) { + dict->SetInteger(net::QuicUtils::ErrorToString(error), + static_cast<int>(error)); + } + + constants_dict->Set("quicError", dict); + } + + // Add information on the relationship between QUIC RST_STREAM error codes + // and their symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + for (net::QuicRstStreamErrorCode error = net::QUIC_STREAM_NO_ERROR; + error < net::QUIC_STREAM_LAST_ERROR; + error = static_cast<net::QuicRstStreamErrorCode>(error + 1)) { + dict->SetInteger(net::QuicUtils::StreamErrorToString(error), + static_cast<int>(error)); + } + + constants_dict->Set("quicRstStreamError", dict); + } + + // Information about the relationship between event phase enums and their + // symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN); + dict->SetInteger("PHASE_END", net::NetLog::PHASE_END); + dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE); + + constants_dict->Set("logEventPhase", dict); + } + + // Information about the relationship between source type enums and + // their symbolic names. + constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue()); + + // Information about the relationship between LogLevel enums and their + // symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + dict->SetInteger("LOG_ALL", net::NetLog::LOG_ALL); + dict->SetInteger("LOG_ALL_BUT_BYTES", net::NetLog::LOG_ALL_BUT_BYTES); + dict->SetInteger("LOG_STRIP_PRIVATE_DATA", + net::NetLog::LOG_STRIP_PRIVATE_DATA); + + constants_dict->Set("logLevelType", dict); + } + + // Information about the relationship between address family enums and + // their symbolic names. + { + base::DictionaryValue* dict = new base::DictionaryValue(); + + dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED", + net::ADDRESS_FAMILY_UNSPECIFIED); + dict->SetInteger("ADDRESS_FAMILY_IPV4", + net::ADDRESS_FAMILY_IPV4); + dict->SetInteger("ADDRESS_FAMILY_IPV6", + net::ADDRESS_FAMILY_IPV6); + + constants_dict->Set("addressFamily", dict); + } + + // Information about how the "time ticks" values we have given it relate to + // actual system times. (We used time ticks throughout since they are stable + // across system clock changes). + { + int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds(); + + int64 cur_time_ticks_ms = + (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds(); + + // If we add this number to a time tick value, it gives the timestamp. + int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms; + + // Chrome on all platforms stores times using the Windows epoch + // (Jan 1 1601), but the javascript wants a unix epoch. + // TODO(eroman): Getting the timestamp relative to the unix epoch should + // be part of the time library. + const int64 kUnixEpochMs = 11644473600000LL; + int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs; + + // Pass it as a string, since it may be too large to fit in an integer. + constants_dict->SetString("timeTickOffset", + base::Int64ToString(tick_to_unix_time_ms)); + } + + // "clientInfo" key is required for some NetLogLogger log readers. + // Provide a default empty value for compatibility. + constants_dict->Set("clientInfo", new base::DictionaryValue()); + + // Add a list of active field experiments. + { + base::FieldTrial::ActiveGroups active_groups; + base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); + base::ListValue* field_trial_groups = new base::ListValue(); + for (base::FieldTrial::ActiveGroups::const_iterator it = + active_groups.begin(); + it != active_groups.end(); ++it) { + field_trial_groups->AppendString(it->trial_name + ":" + + it->group_name); + } + constants_dict->Set("activeFieldTrialGroups", field_trial_groups); + } + + return constants_dict.Pass(); +} + +NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo( + URLRequestContext* context, int info_sources) { + scoped_ptr<base::DictionaryValue> net_info_dict(new base::DictionaryValue()); + + // TODO(mmenke): The code for most of these sources should probably be moved + // into the sources themselves. + if (info_sources & NET_INFO_PROXY_SETTINGS) { + net::ProxyService* proxy_service = context->proxy_service(); + + base::DictionaryValue* dict = new base::DictionaryValue(); + if (proxy_service->fetched_config().is_valid()) + dict->Set("original", proxy_service->fetched_config().ToValue()); + if (proxy_service->config().is_valid()) + dict->Set("effective", proxy_service->config().ToValue()); + + net_info_dict->Set(NetInfoSourceToString(NET_INFO_PROXY_SETTINGS), dict); + } + + if (info_sources & NET_INFO_BAD_PROXIES) { + const net::ProxyRetryInfoMap& bad_proxies_map = + context->proxy_service()->proxy_retry_info(); + + base::ListValue* list = new base::ListValue(); + + for (net::ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin(); + it != bad_proxies_map.end(); ++it) { + const std::string& proxy_uri = it->first; + const net::ProxyRetryInfo& retry_info = it->second; + + base::DictionaryValue* dict = new base::DictionaryValue(); + dict->SetString("proxy_uri", proxy_uri); + dict->SetString("bad_until", + net::NetLog::TickCountToString(retry_info.bad_until)); + + list->Append(dict); + } + + net_info_dict->Set(NetInfoSourceToString(NET_INFO_BAD_PROXIES), list); + } + + if (info_sources & NET_INFO_HOST_RESOLVER) { + net::HostResolver* host_resolver = context->host_resolver(); + DCHECK(host_resolver); + net::HostCache* cache = host_resolver->GetHostCache(); + if (cache) { + base::DictionaryValue* dict = new base::DictionaryValue(); + base::Value* dns_config = host_resolver->GetDnsConfigAsValue(); + if (dns_config) + dict->Set("dns_config", dns_config); + + dict->SetInteger( + "default_address_family", + static_cast<int>(host_resolver->GetDefaultAddressFamily())); + + base::DictionaryValue* cache_info_dict = new base::DictionaryValue(); + + cache_info_dict->SetInteger( + "capacity", + static_cast<int>(cache->max_entries())); + + base::ListValue* entry_list = new base::ListValue(); + + net::HostCache::EntryMap::Iterator it(cache->entries()); + for (; it.HasNext(); it.Advance()) { + const net::HostCache::Key& key = it.key(); + const net::HostCache::Entry& entry = it.value(); + + base::DictionaryValue* entry_dict = new base::DictionaryValue(); + + entry_dict->SetString("hostname", key.hostname); + entry_dict->SetInteger("address_family", + static_cast<int>(key.address_family)); + entry_dict->SetString("expiration", + net::NetLog::TickCountToString(it.expiration())); + + if (entry.error != net::OK) { + entry_dict->SetInteger("error", entry.error); + } else { + // Append all of the resolved addresses. + base::ListValue* address_list = new base::ListValue(); + for (size_t i = 0; i < entry.addrlist.size(); ++i) { + address_list->AppendString(entry.addrlist[i].ToStringWithoutPort()); + } + entry_dict->Set("addresses", address_list); + } + + entry_list->Append(entry_dict); + } + + cache_info_dict->Set("entries", entry_list); + dict->Set("cache", cache_info_dict); + net_info_dict->Set(NetInfoSourceToString(NET_INFO_HOST_RESOLVER), dict); + } + } + + net::HttpNetworkSession* http_network_session = + context->http_transaction_factory()->GetSession(); + + if (info_sources & NET_INFO_SOCKET_POOL) { + net_info_dict->Set(NetInfoSourceToString(NET_INFO_SOCKET_POOL), + http_network_session->SocketPoolInfoToValue()); + } + + if (info_sources & NET_INFO_SPDY_SESSIONS) { + net_info_dict->Set(NetInfoSourceToString(NET_INFO_SPDY_SESSIONS), + http_network_session->SpdySessionPoolInfoToValue()); + } + + if (info_sources & NET_INFO_SPDY_STATUS) { + base::DictionaryValue* status_dict = new base::DictionaryValue(); + + status_dict->SetBoolean("spdy_enabled", + net::HttpStreamFactory::spdy_enabled()); + status_dict->SetBoolean( + "use_alternate_protocols", + http_network_session->params().use_alternate_protocols); + status_dict->SetBoolean( + "force_spdy_over_ssl", + http_network_session->params().force_spdy_over_ssl); + status_dict->SetBoolean( + "force_spdy_always", + http_network_session->params().force_spdy_always); + + std::vector<std::string> next_protos; + http_network_session->GetNextProtos(&next_protos); + std::string next_protos_string = JoinString(next_protos, ','); + status_dict->SetString("next_protos", next_protos_string); + + net_info_dict->Set(NetInfoSourceToString(NET_INFO_SPDY_STATUS), + status_dict); + } + + if (info_sources & NET_INFO_SPDY_ALT_PROTO_MAPPINGS) { + base::ListValue* dict_list = new base::ListValue(); + + const net::HttpServerProperties& http_server_properties = + *context->http_server_properties(); + + const net::AlternateProtocolMap& map = + http_server_properties.alternate_protocol_map(); + + for (net::AlternateProtocolMap::const_iterator it = map.begin(); + it != map.end(); ++it) { + base::DictionaryValue* dict = new base::DictionaryValue(); + dict->SetString("host_port_pair", it->first.ToString()); + dict->SetString("alternate_protocol", it->second.ToString()); + dict_list->Append(dict); + } + + net_info_dict->Set(NetInfoSourceToString(NET_INFO_SPDY_ALT_PROTO_MAPPINGS), + dict_list); + } + + if (info_sources & NET_INFO_QUIC) { + net_info_dict->Set(NetInfoSourceToString(NET_INFO_QUIC), + http_network_session->QuicInfoToValue()); + } + + if (info_sources & NET_INFO_HTTP_CACHE) { + base::DictionaryValue* info_dict = new base::DictionaryValue(); + base::DictionaryValue* stats_dict = new base::DictionaryValue(); + + disk_cache::Backend* disk_cache = GetDiskCacheBackend(context); + + if (disk_cache) { + // Extract the statistics key/value pairs from the backend. + base::StringPairs stats; + disk_cache->GetStats(&stats); + for (size_t i = 0; i < stats.size(); ++i) { + stats_dict->SetStringWithoutPathExpansion( + stats[i].first, stats[i].second); + } + } + info_dict->Set("stats", stats_dict); + + net_info_dict->Set(NetInfoSourceToString(NET_INFO_HTTP_CACHE), + info_dict); + } + + return net_info_dict.Pass(); +} + +} // namespace net diff --git a/chromium/net/base/net_log_util.h b/chromium/net/base/net_log_util.h new file mode 100644 index 00000000000..d9627da416e --- /dev/null +++ b/chromium/net/base/net_log_util.h @@ -0,0 +1,43 @@ +// Copyright 2014 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 NET_BASE_NET_LOG_UTIL_H_ +#define NET_BASE_NET_LOG_UTIL_H_ + +#include "base/memory/scoped_ptr.h" +#include "net/base/net_export.h" + +namespace base { +class DictionaryValue; +class Value; +} + +namespace net { + +class URLRequestContext; + +// A set of flags that can be OR'd together to request specific information +// about the current state of the URLRequestContext. See GetNetInfo, below. +enum NetInfoSource { +#define NET_INFO_SOURCE(label, string, value) NET_INFO_ ## label = value, +#include "net/base/net_info_source_list.h" +#undef NET_INFO_SOURCE + NET_INFO_ALL_SOURCES = -1, +}; + +// Utility methods for creating NetLog dumps. + +// Create a dictionary containing legend for net/ constants. +NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetConstants(); + +// Retrieves a dictionary containing information about the current state of +// |context|. |info_sources| is a set of NetInfoSources OR'd together, +// indicating just what information is being requested. Each NetInfoSource adds +// one top-level entry to the returned dictionary. +NET_EXPORT scoped_ptr<base::DictionaryValue> GetNetInfo( + URLRequestContext* context, int info_sources); + +} // namespace net + +#endif // NET_BASE_NET_LOG_UTIL_H_ diff --git a/chromium/net/base/net_log_util_unittest.cc b/chromium/net/base/net_log_util_unittest.cc new file mode 100644 index 00000000000..e5cc3a33fb2 --- /dev/null +++ b/chromium/net/base/net_log_util_unittest.cc @@ -0,0 +1,54 @@ +// Copyright 2014 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 "net/base/net_log_util.h" + +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/http/http_cache.h" +#include "net/http/http_transaction.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +// Make sure GetNetConstants doesn't crash. +TEST(NetLogUtil, GetNetConstants) { + scoped_ptr<base::Value> constants(GetNetConstants()); +} + +// Make sure GetNetInfo doesn't crash when called on contexts with and without +// caches, and they have the same number of elements. +TEST(NetLogUtil, GetNetInfo) { + TestURLRequestContext context; + net::HttpCache* http_cache = context.http_transaction_factory()->GetCache(); + + // Get NetInfo when there's no cache backend (It's only created on first use). + EXPECT_FALSE(http_cache->GetCurrentBackend()); + scoped_ptr<base::DictionaryValue> net_info_without_cache( + GetNetInfo(&context, NET_INFO_ALL_SOURCES)); + EXPECT_FALSE(http_cache->GetCurrentBackend()); + EXPECT_GT(net_info_without_cache->size(), 0u); + + // Fore creation of a cache backend, and get NetInfo again. + disk_cache::Backend* backend = NULL; + EXPECT_EQ( + OK, + context.http_transaction_factory()->GetCache()->GetBackend( + &backend, TestCompletionCallback().callback())); + EXPECT_TRUE(http_cache->GetCurrentBackend()); + scoped_ptr<base::DictionaryValue> net_info_with_cache( + GetNetInfo(&context, NET_INFO_ALL_SOURCES)); + EXPECT_GT(net_info_with_cache->size(), 0u); + + EXPECT_EQ(net_info_without_cache->size(), net_info_with_cache->size()); +} + +} // namespace + +} // namespace net diff --git a/chromium/net/base/net_string_util_icu_alternatives_android.cc b/chromium/net/base/net_string_util_icu_alternatives_android.cc index ca0630328f5..ca0e7f0315d 100644 --- a/chromium/net/base/net_string_util_icu_alternatives_android.cc +++ b/chromium/net/base/net_string_util_icu_alternatives_android.cc @@ -20,12 +20,13 @@ namespace { ScopedJavaLocalRef<jstring> ConvertToJstring(const std::string& text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - jobject java_byte_buffer = - env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + ScopedJavaLocalRef<jobject> java_byte_buffer( + env, + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length())); base::android::ScopedJavaLocalRef<jstring> java_charset = base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); ScopedJavaLocalRef<jstring> java_result = - android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer, + android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer.obj(), java_charset.obj()); return java_result; } @@ -36,13 +37,14 @@ ScopedJavaLocalRef<jstring> ConvertToJstring(const std::string& text, ScopedJavaLocalRef<jstring> ConvertToNormalizedJstring( const std::string& text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - jobject java_byte_buffer = - env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + ScopedJavaLocalRef<jobject> java_byte_buffer( + env, + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length())); base::android::ScopedJavaLocalRef<jstring> java_charset = base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); ScopedJavaLocalRef<jstring> java_result = android::Java_NetStringUtil_convertToUnicodeAndNormalize( - env, java_byte_buffer, java_charset.obj()); + env, java_byte_buffer.obj(), java_charset.obj()); return java_result; } @@ -51,13 +53,14 @@ ScopedJavaLocalRef<jstring> ConvertToNormalizedJstring( ScopedJavaLocalRef<jstring> ConvertToJstringWithSubstitutions( const std::string& text, const char* charset) { JNIEnv* env = base::android::AttachCurrentThread(); - jobject java_byte_buffer = - env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + ScopedJavaLocalRef<jobject> java_byte_buffer( + env, + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length())); base::android::ScopedJavaLocalRef<jstring> java_charset = base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); ScopedJavaLocalRef<jstring> java_result = android::Java_NetStringUtil_convertToUnicodeWithSubstitutions( - env, java_byte_buffer, java_charset.obj()); + env, java_byte_buffer.obj(), java_charset.obj()); return java_result; } diff --git a/chromium/net/base/net_util.cc b/chromium/net/base/net_util.cc index 5b3d65e515b..b9cf59f1789 100644 --- a/chromium/net/base/net_util.cc +++ b/chromium/net/base/net_util.cc @@ -5,6 +5,7 @@ #include "net/base/net_util.h" #include <errno.h> +#include <string.h> #include <algorithm> #include <iterator> @@ -43,7 +44,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/sys_byteorder.h" #include "base/values.h" -#include "grit/net_resources.h" #include "url/gurl.h" #include "url/url_canon.h" #include "url/url_canon_ip.h" @@ -51,6 +51,7 @@ #include "net/base/dns_util.h" #include "net/base/net_module.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "net/grit/net_resources.h" #include "net/http/http_content_disposition.h" #if defined(OS_ANDROID) @@ -250,8 +251,7 @@ inline bool IsHostCharAlphanumeric(char c) { return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')); } -bool IsCanonicalizedHostCompliant(const std::string& host, - const std::string& desired_tld) { +bool IsCanonicalizedHostCompliant(const std::string& host) { if (host.empty()) return false; @@ -281,8 +281,7 @@ bool IsCanonicalizedHostCompliant(const std::string& host, } } - return most_recent_component_started_alphanumeric || - (!desired_tld.empty() && IsHostCharAlphanumeric(desired_tld[0])); + return most_recent_component_started_alphanumeric; } base::string16 StripWWW(const base::string16& text) { @@ -375,6 +374,23 @@ bool ParseHostAndPort(std::string::const_iterator host_and_port_begin, if (port_component.len == 0) return false; // Reject inputs like "foo:" + unsigned char tmp_ipv6_addr[16]; + + // If the hostname starts with a bracket, it is either an IPv6 literal or + // invalid. If it is an IPv6 literal then strip the brackets. + if (hostname_component.len > 0 && + auth_begin[hostname_component.begin] == '[') { + if (auth_begin[hostname_component.end() - 1] == ']' && + url::IPv6AddressToNumber( + auth_begin, hostname_component, tmp_ipv6_addr)) { + // Strip the brackets. + hostname_component.begin++; + hostname_component.len -= 2; + } else { + return false; + } + } + // Pass results back to caller. host->assign(auth_begin + hostname_component.begin, hostname_component.len); *port = parsed_port_number; @@ -501,6 +517,18 @@ bool IsIPAddressReserved(const IPAddressNumber& host_addr) { return false; } +SockaddrStorage::SockaddrStorage(const SockaddrStorage& other) + : addr_len(other.addr_len), + addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) { + memcpy(addr, other.addr, addr_len); +} + +void SockaddrStorage::operator=(const SockaddrStorage& other) { + addr_len = other.addr_len; + // addr is already set to &this->addr_storage by default ctor. + memcpy(addr, other.addr, addr_len); +} + // Extracts the address and port portions of a sockaddr. bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, socklen_t sock_addr_len, @@ -786,6 +814,28 @@ int ConvertAddressFamily(AddressFamily address_family) { return AF_UNSPEC; } +bool ParseURLHostnameToNumber(const std::string& hostname, + IPAddressNumber* ip_number) { + // |hostname| is an already canoncalized hostname, conforming to RFC 3986. + // For an IP address, this is defined in Section 3.2.2 of RFC 3986, with + // the canonical form for IPv6 addresses defined in Section 4 of RFC 5952. + url::Component host_comp(0, hostname.size()); + + // If it has a bracket, try parsing it as an IPv6 address. + if (hostname[0] == '[') { + ip_number->resize(16); // 128 bits. + return url::IPv6AddressToNumber( + hostname.data(), host_comp, &(*ip_number)[0]); + } + + // Otherwise, try IPv4. + ip_number->resize(4); // 32 bits. + int num_components; + url::CanonHostInfo::Family family = url::IPv4AddressToNumber( + hostname.data(), host_comp, &(*ip_number)[0], &num_components); + return family == url::CanonHostInfo::IPV4; +} + bool ParseIPLiteralToNumber(const std::string& ip_literal, IPAddressNumber* ip_number) { // |ip_literal| could be either a IPv4 or an IPv6 literal. If it contains @@ -969,13 +1019,15 @@ NetworkInterface::NetworkInterface(const std::string& name, uint32 interface_index, NetworkChangeNotifier::ConnectionType type, const IPAddressNumber& address, - size_t network_prefix) + uint32 network_prefix, + int ip_address_attributes) : name(name), friendly_name(friendly_name), interface_index(interface_index), type(type), address(address), - network_prefix(network_prefix) { + network_prefix(network_prefix), + ip_address_attributes(ip_address_attributes) { } NetworkInterface::~NetworkInterface() { @@ -1003,4 +1055,7 @@ unsigned MaskPrefixLength(const IPAddressNumber& mask) { return CommonPrefixLength(mask, all_ones); } +ScopedWifiOptions::~ScopedWifiOptions() { +} + } // namespace net diff --git a/chromium/net/base/net_util.h b/chromium/net/base/net_util.h index d83744fb596..72ac169a24c 100644 --- a/chromium/net/base/net_util.h +++ b/chromium/net/base/net_util.h @@ -81,8 +81,12 @@ NET_EXPORT_PRIVATE extern size_t GetCountOfExplicitlyAllowedPorts(); // Saves the result into |*host| and |*port|. If the input did not have // the optional port, sets |*port| to -1. // Returns true if the parsing was successful, false otherwise. -// The returned host is NOT canonicalized, and may be invalid. If <host> is -// an IPv6 literal address, the returned host includes the square brackets. +// The returned host is NOT canonicalized, and may be invalid. +// +// IPv6 literals must be specified in a bracketed form, for instance: +// [::1]:90 and [::1] +// +// The resultant |*host| in both cases will be "::1" (not bracketed). NET_EXPORT bool ParseHostAndPort( std::string::const_iterator host_and_port_begin, std::string::const_iterator host_and_port_end, @@ -114,6 +118,9 @@ NET_EXPORT bool IsIPAddressReserved(const IPAddressNumber& address); struct SockaddrStorage { SockaddrStorage() : addr_len(sizeof(addr_storage)), addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) {} + SockaddrStorage(const SockaddrStorage& other); + void operator=(const SockaddrStorage& other); + struct sockaddr_storage addr_storage; socklen_t addr_len; struct sockaddr* const addr; @@ -208,15 +215,10 @@ NET_EXPORT std::string CanonicalizeHost(const std::string& host, // * Each component ends with an alphanumeric character or '-' // * The last component begins with an alphanumeric character // * Optional trailing dot after last component (means "treat as FQDN") -// If |desired_tld| is non-NULL, the host will only be considered invalid if -// appending it as a trailing component still results in an invalid host. This -// helps us avoid marking as "invalid" user attempts to open, say, "www.-9.com" -// by typing -, 9, <ctrl>+<enter>. // // NOTE: You should only pass in hosts that have been returned from // CanonicalizeHost(), or you may not get accurate results. -NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host, - const std::string& desired_tld); +NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host); // Call these functions to get the html snippet for a directory listing. // The return values of both functions are in UTF-8. @@ -369,10 +371,15 @@ NET_EXPORT_PRIVATE AddressFamily GetAddressFamily( // Maps the given AddressFamily to either AF_INET, AF_INET6 or AF_UNSPEC. NET_EXPORT_PRIVATE int ConvertAddressFamily(AddressFamily address_family); +// Parses a URL-safe IP literal (see RFC 3986, Sec 3.2.2) to its numeric value. +// Returns true on success, and fills |ip_number| with the numeric value +NET_EXPORT bool ParseURLHostnameToNumber(const std::string& hostname, + IPAddressNumber* ip_number); + // Parses an IP address literal (either IPv4 or IPv6) to its numeric value. // Returns true on success and fills |ip_number| with the numeric value. -NET_EXPORT_PRIVATE bool ParseIPLiteralToNumber(const std::string& ip_literal, - IPAddressNumber* ip_number); +NET_EXPORT bool ParseIPLiteralToNumber(const std::string& ip_literal, + IPAddressNumber* ip_number); // Converts an IPv4 address to an IPv4-mapped IPv6 address. // For example 192.168.0.1 would be converted to ::ffff:192.168.0.1. @@ -430,6 +437,24 @@ NET_EXPORT_PRIVATE int GetPortFromSockaddr(const struct sockaddr* address, // machine. NET_EXPORT_PRIVATE bool IsLocalhost(const std::string& host); +// A subset of IP address attributes which are actionable by the +// application layer. Currently unimplemented for all hosts; +// IP_ADDRESS_ATTRIBUTE_NONE is always returned. +enum IPAddressAttributes { + IP_ADDRESS_ATTRIBUTE_NONE = 0, + + // A temporary address is dynamic by nature and will not contain MAC + // address. Presence of MAC address in IPv6 addresses can be used to + // track an endpoint and cause privacy concern. Please refer to + // RFC4941. + IP_ADDRESS_ATTRIBUTE_TEMPORARY = 1 << 0, + + // A temporary address could become deprecated once the preferred + // lifetime is reached. It is still valid but shouldn't be used to + // create new connections. + IP_ADDRESS_ATTRIBUTE_DEPRECATED = 1 << 1, +}; + // struct that is used by GetNetworkList() to represent a network // interface. struct NET_EXPORT NetworkInterface { @@ -439,7 +464,8 @@ struct NET_EXPORT NetworkInterface { uint32 interface_index, NetworkChangeNotifier::ConnectionType type, const IPAddressNumber& address, - size_t network_prefix); + uint32 network_prefix, + int ip_address_attributes); ~NetworkInterface(); std::string name; @@ -447,7 +473,8 @@ struct NET_EXPORT NetworkInterface { uint32 interface_index; // Always 0 on Android. NetworkChangeNotifier::ConnectionType type; IPAddressNumber address; - size_t network_prefix; + uint32 network_prefix; + int ip_address_attributes; // Combination of |IPAddressAttributes|. }; typedef std::vector<NetworkInterface> NetworkInterfaceList; @@ -490,6 +517,28 @@ enum WifiPHYLayerProtocol { // Currently only available on OS_WIN. NET_EXPORT WifiPHYLayerProtocol GetWifiPHYLayerProtocol(); +enum WifiOptions { + // Disables background SSID scans. + WIFI_OPTIONS_DISABLE_SCAN = 1 << 0, + // Enables media streaming mode. + WIFI_OPTIONS_MEDIA_STREAMING_MODE = 1 << 1 +}; + +class NET_EXPORT ScopedWifiOptions { + public: + ScopedWifiOptions() {} + virtual ~ScopedWifiOptions(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedWifiOptions); +}; + +// Set temporary options on all wifi interfaces. +// |options| is an ORed bitfield of WifiOptions. +// Options are automatically disabled when the scoped pointer +// is freed. Currently only available on OS_WIN. +NET_EXPORT scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options); + // Returns number of matching initial bits between the addresses |a1| and |a2|. unsigned CommonPrefixLength(const IPAddressNumber& a1, const IPAddressNumber& a2); diff --git a/chromium/net/base/net_util_icu.cc b/chromium/net/base/net_util_icu.cc index 4094feeff74..8526edaffbe 100644 --- a/chromium/net/base/net_util_icu.cc +++ b/chromium/net/base/net_util_icu.cc @@ -491,9 +491,9 @@ class HostComponentTransform : public AppendComponentTransform { } private: - virtual base::string16 Execute( + base::string16 Execute( const std::string& component_text, - base::OffsetAdjuster::Adjustments* adjustments) const OVERRIDE { + base::OffsetAdjuster::Adjustments* adjustments) const override { return IDNToUnicodeWithAdjustments(component_text, languages_, adjustments); } @@ -508,9 +508,9 @@ class NonHostComponentTransform : public AppendComponentTransform { } private: - virtual base::string16 Execute( + base::string16 Execute( const std::string& component_text, - base::OffsetAdjuster::Adjustments* adjustments) const OVERRIDE { + base::OffsetAdjuster::Adjustments* adjustments) const override { return (unescape_rules_ == UnescapeRule::NONE) ? base::UTF8ToUTF16WithAdjustments(component_text, adjustments) : UnescapeAndDecodeUTF8URLComponentWithAdjustments(component_text, diff --git a/chromium/net/base/net_util_icu_unittest.cc b/chromium/net/base/net_util_icu_unittest.cc index 9beb4349b57..d92b9d162e1 100644 --- a/chromium/net/base/net_util_icu_unittest.cc +++ b/chromium/net/base/net_util_icu_unittest.cc @@ -411,7 +411,7 @@ void CheckAdjustedOffsets(const std::string& url_string, } // anonymous namespace TEST(NetUtilTest, IDNToUnicodeFast) { - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) { + for (size_t i = 0; i < arraysize(idn_cases); i++) { for (size_t j = 0; j < arraysize(kLanguages); j++) { // ja || zh-TW,en || ko,ja -> IDNToUnicodeSlow if (j == 3 || j == 17 || j == 18) @@ -427,7 +427,7 @@ TEST(NetUtilTest, IDNToUnicodeFast) { } TEST(NetUtilTest, IDNToUnicodeSlow) { - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) { + for (size_t i = 0; i < arraysize(idn_cases); i++) { for (size_t j = 0; j < arraysize(kLanguages); j++) { // !(ja || zh-TW,en || ko,ja) -> IDNToUnicodeFast if (!(j == 3 || j == 17 || j == 18)) @@ -506,7 +506,7 @@ TEST(NetUtilTest, GetDirectoryListingEntry) { ",0,\"9.8 kB\",\"\");</script>\n"}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { + for (size_t i = 0; i < arraysize(test_cases); ++i) { const std::string results = GetDirectoryListingEntry( WideToUTF16(test_cases[i].name), test_cases[i].raw_bytes, diff --git a/chromium/net/base/net_util_posix.cc b/chromium/net/base/net_util_posix.cc index 315e9ed1a23..a2fa6cdf2ce 100644 --- a/chromium/net/base/net_util_posix.cc +++ b/chromium/net/base/net_util_posix.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" @@ -18,11 +19,16 @@ #include "net/base/net_errors.h" #include "url/gurl.h" -#if !defined(OS_ANDROID) && !defined(OS_NACL) +#if !defined(OS_NACL) +#if defined(OS_MACOSX) #include <ifaddrs.h> +#else +#include "net/base/address_tracker_linux.h" +#include "net/base/net_util_posix.h" +#endif // OS_MACOSX #include <net/if.h> #include <netinet/in.h> -#endif +#endif // !defined(OS_NACL) #if defined(OS_MACOSX) && !defined(OS_IOS) #include <net/if_media.h> @@ -30,15 +36,48 @@ #include <sys/ioctl.h> #endif -#if defined(OS_ANDROID) -#include "net/android/network_library.h" -#endif - namespace net { namespace { -#if !defined(OS_ANDROID) +// The application layer can pass |policy| defined in net_util.h to +// request filtering out certain type of interfaces. +bool ShouldIgnoreInterface(const std::string& name, int policy) { + // Filter out VMware interfaces, typically named vmnet1 and vmnet8, + // which might not be useful for use cases like WebRTC. + if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) && + ((name.find("vmnet") != std::string::npos) || + (name.find("vnic") != std::string::npos))) { + return true; + } + + return false; +} + +// Check if the address is unspecified (i.e. made of zeroes) or loopback. +bool IsLoopbackOrUnspecifiedAddress(const sockaddr* addr) { + if (addr->sa_family == AF_INET6) { + const struct sockaddr_in6* addr_in6 = + reinterpret_cast<const struct sockaddr_in6*>(addr); + const struct in6_addr* sin6_addr = &addr_in6->sin6_addr; + if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) { + return true; + } + } else if (addr->sa_family == AF_INET) { + const struct sockaddr_in* addr_in = + reinterpret_cast<const struct sockaddr_in*>(addr); + if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK || + addr_in->sin_addr.s_addr == 0) { + return true; + } + } else { + // Skip non-IP addresses. + return true; + } + return false; +} + +#if defined(OS_MACOSX) struct NetworkInterfaceInfo { NetworkInterfaceInfo() : permanent(true) { } @@ -82,10 +121,7 @@ void RemovePermanentIPv6AddressesWhereTemporaryExists( } } -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - +#if !defined(OS_IOS) NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType( int addr_family, const std::string& interface_name) { NetworkChangeNotifier::ConnectionType type = @@ -110,53 +146,160 @@ NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType( return type; } -#endif +#endif // !defined(OS_IOS) +#elif !defined(OS_NACL) // OS_MACOSX + +// Convert platform native IPv6 address attributes to net IP address +// attributes and drop ones that can't be used by the application +// layer. +bool TryConvertNativeToNetIPAttributes(int native_attributes, + int* net_attributes) { + // For Linux/ChromeOS/Android, we disallow addresses with attributes + // IFA_F_OPTIMISTIC, IFA_F_DADFAILED, and IFA_F_TENTATIVE as these + // are still progressing through duplicated address detection (DAD) + // and shouldn't be used by the application layer until DAD process + // is completed. + if (native_attributes & ( +#if !defined(OS_ANDROID) + IFA_F_OPTIMISTIC | IFA_F_DADFAILED | +#endif // !OS_ANDROID + IFA_F_TENTATIVE)) { + return false; + } + + if (native_attributes & IFA_F_TEMPORARY) { + *net_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY; + } + + if (native_attributes & IFA_F_DEPRECATED) { + *net_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED; + } + return true; +} +#endif // OS_MACOSX } // namespace -bool GetNetworkList(NetworkInterfaceList* networks, int policy) { -#if defined(OS_NACL) - NOTIMPLEMENTED(); - return false; -#elif defined(OS_ANDROID) - std::string network_list = android::GetNetworkList(); - base::StringTokenizer network_interfaces(network_list, "\n"); - while (network_interfaces.GetNext()) { - std::string network_item = network_interfaces.token(); - base::StringTokenizer network_tokenizer(network_item, "\t"); - CHECK(network_tokenizer.GetNext()); - std::string name = network_tokenizer.token(); - - CHECK(network_tokenizer.GetNext()); - std::string interface_address = network_tokenizer.token(); - IPAddressNumber address; - size_t network_prefix = 0; - CHECK(ParseCIDRBlock(network_tokenizer.token(), - &address, - &network_prefix)); - - CHECK(network_tokenizer.GetNext()); - uint32 index = 0; - CHECK(base::StringToUint(network_tokenizer.token(), &index)); +namespace internal { + +#if !defined(OS_MACOSX) && !defined(OS_NACL) + +inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) { +#if defined(OS_ANDROID) + return ip.begin(); +#else + return ip.data(); +#endif +} + +bool GetNetworkListImpl( + NetworkInterfaceList* networks, + int policy, + const base::hash_set<int>& online_links, + const internal::AddressTrackerLinux::AddressMap& address_map, + GetInterfaceNameFunction get_interface_name) { + std::map<int, std::string> ifnames; + + for (internal::AddressTrackerLinux::AddressMap::const_iterator it = + address_map.begin(); + it != address_map.end(); + ++it) { + // Ignore addresses whose links are not online. + if (online_links.find(it->second.ifa_index) == online_links.end()) + continue; + + sockaddr_storage sock_addr; + socklen_t sock_len = sizeof(sockaddr_storage); + + // Convert to sockaddr for next check. + if (!IPEndPoint(it->first, 0) + .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addr), &sock_len)) { + continue; + } + + // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses + if (IsLoopbackOrUnspecifiedAddress(reinterpret_cast<sockaddr*>(&sock_addr))) + continue; + + int ip_attributes = IP_ADDRESS_ATTRIBUTE_NONE; + + if (it->second.ifa_family == AF_INET6) { + // Ignore addresses whose attributes are not actionable by + // the application layer. + if (!TryConvertNativeToNetIPAttributes(it->second.ifa_flags, + &ip_attributes)) + continue; + } + + // Find the name of this link. + std::map<int, std::string>::const_iterator itname = + ifnames.find(it->second.ifa_index); + std::string ifname; + if (itname == ifnames.end()) { + char buffer[IF_NAMESIZE] = {0}; + if (get_interface_name(it->second.ifa_index, buffer)) { + ifname = ifnames[it->second.ifa_index] = buffer; + } else { + // Ignore addresses whose interface name can't be retrieved. + continue; + } + } else { + ifname = itname->second; + } + + // Based on the interface name and policy, determine whether we + // should ignore it. + if (ShouldIgnoreInterface(ifname, policy)) + continue; networks->push_back( - NetworkInterface(name, name, index, + NetworkInterface(ifname, + ifname, + it->second.ifa_index, NetworkChangeNotifier::CONNECTION_UNKNOWN, - address, network_prefix)); + it->first, + it->second.ifa_prefixlen, + ip_attributes)); } + return true; -#else +} +#endif + +} // namespace internal + +bool GetNetworkList(NetworkInterfaceList* networks, int policy) { + if (networks == NULL) + return false; +#if defined(OS_NACL) + NOTIMPLEMENTED(); + return false; +#elif !defined(OS_MACOSX) + + internal::AddressTrackerLinux tracker; + tracker.Init(); + + return internal::GetNetworkListImpl(networks, + policy, + tracker.GetOnlineLinks(), + tracker.GetAddressMap(), + &if_indextoname); + +#else // Only OS_MACOSX and OS_IOS will run the code below + // getifaddrs() may require IO operations. base::ThreadRestrictions::AssertIOAllowed(); +#if !defined(OS_IOS) int ioctl_socket = -1; if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { // we need a socket to query information about temporary address. ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0); DCHECK_GT(ioctl_socket, 0); } +#endif - ifaddrs *interfaces; + ifaddrs* interfaces; if (getifaddrs(&interfaces) < 0) { PLOG(ERROR) << "getifaddrs"; return false; @@ -180,41 +323,26 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses // configured on non-loopback interfaces. + if (IsLoopbackOrUnspecifiedAddress(addr)) + continue; + int addr_size = 0; if (addr->sa_family == AF_INET6) { - struct sockaddr_in6* addr_in6 = - reinterpret_cast<struct sockaddr_in6*>(addr); - struct in6_addr* sin6_addr = &addr_in6->sin6_addr; - addr_size = sizeof(*addr_in6); - if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || - IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) { - continue; - } + addr_size = sizeof(sockaddr_in6); } else if (addr->sa_family == AF_INET) { - struct sockaddr_in* addr_in = - reinterpret_cast<struct sockaddr_in*>(addr); - addr_size = sizeof(*addr_in); - if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK || - addr_in->sin_addr.s_addr == 0) { - continue; - } - } else { - // Skip non-IP addresses. - continue; + addr_size = sizeof(sockaddr_in); } const std::string& name = interface->ifa_name; // Filter out VMware interfaces, typically named vmnet1 and vmnet8. - if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) && - ((name.find("vmnet") != std::string::npos) || - (name.find("vnic") != std::string::npos))) { + if (ShouldIgnoreInterface(name, policy)) { continue; } NetworkInterfaceInfo network_info; NetworkChangeNotifier::ConnectionType connection_type = NetworkChangeNotifier::CONNECTION_UNKNOWN; -#if defined(OS_MACOSX) && !defined(OS_IOS) +#if !defined(OS_IOS) // Check if this is a temporary address. Currently this is only supported // on Mac. if ((policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) && @@ -245,17 +373,23 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { net_mask = MaskPrefixLength(netmask.address()); } } - network_info.interface = NetworkInterface( - name, name, if_nametoindex(name.c_str()), - connection_type, address.address(), net_mask); + network_info.interface = NetworkInterface(name, + name, + if_nametoindex(name.c_str()), + connection_type, + address.address(), + net_mask, + IP_ADDRESS_ATTRIBUTE_NONE); network_infos.push_back(NetworkInterfaceInfo(network_info)); } } freeifaddrs(interfaces); +#if !defined(OS_IOS) if (ioctl_socket >= 0) { close(ioctl_socket); } +#endif if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { RemovePermanentIPv6AddressesWhereTemporaryExists(&network_infos); @@ -272,4 +406,9 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; } +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(); +} + + } // namespace net diff --git a/chromium/net/base/net_util_posix.h b/chromium/net/base/net_util_posix.h new file mode 100644 index 00000000000..b553d1c9144 --- /dev/null +++ b/chromium/net/base/net_util_posix.h @@ -0,0 +1,31 @@ +// Copyright (c) 2014 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 NET_BASE_NET_UTIL_POSIX_H_ +#define NET_BASE_NET_UTIL_POSIX_H_ + +// This file is only used to expose some of the internals +// of net_util_posix.cc to tests. + +namespace net { +namespace internal { + +#if !defined(OS_MACOSX) && !defined(OS_NACL) +typedef char* (*GetInterfaceNameFunction)(unsigned int interface_index, + char* ifname); + +NET_EXPORT bool GetNetworkListImpl( + NetworkInterfaceList* networks, + int policy, + const base::hash_set<int>& online_links, + const internal::AddressTrackerLinux::AddressMap& address_map, + GetInterfaceNameFunction get_interface_name); + +#endif // !OS_MACOSX && !OS_NACL + +} // namespace internal + +} // namespace net + +#endif // NET_BASE_NET_UTIL_POSIX_H_ diff --git a/chromium/net/base/net_util_unittest.cc b/chromium/net/base/net_util_unittest.cc index 674a7259121..45f08571c41 100644 --- a/chromium/net/base/net_util_unittest.cc +++ b/chromium/net/base/net_util_unittest.cc @@ -17,6 +17,11 @@ #include "base/strings/utf_string_conversions.h" #include "base/sys_byteorder.h" #include "base/time/time.h" + +#if !defined(OS_NACL) && !defined(OS_WIN) +#include <net/if.h> +#include <netinet/in.h> +#endif // !OS_NACL && !OS_WIN #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -24,10 +29,17 @@ #include <iphlpapi.h> #include <objbase.h> #include "base/win/windows_version.h" -#elif !defined(OS_ANDROID) -#include <net/if.h> +#include "net/base/net_util_win.h" #endif // OS_WIN +#if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_WIN) +#include "net/base/address_tracker_linux.h" +#endif // !OS_MACOSX && !OS_NACL && !OS_WIN + +#if !defined(OS_WIN) +#include "net/base/net_util_posix.h" +#endif // !OS_WIN + using base::ASCIIToUTF16; using base::WideToUTF16; @@ -40,12 +52,6 @@ struct HeaderCase { const char* expected; }; -struct CompliantHostCase { - const char* host; - const char* desired_tld; - bool expected_output; -}; - // Fills in sockaddr for the given 32-bit address (IPv4.) // |bytes| should be an array of length 4. void MakeIPv4Address(const uint8* bytes, int port, SockaddrStorage* storage) { @@ -123,7 +129,7 @@ TEST(NetUtilTest, GetIdentityFromURL) { "p&ssword", }, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i, tests[i].input_url)); GURL url(tests[i].input_url); @@ -185,50 +191,53 @@ TEST(NetUtilTest, GetSpecificHeader) { }; // Test first with google_headers. - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::string result = GetSpecificHeader(google_headers, tests[i].header_name); EXPECT_EQ(result, tests[i].expected); } // Test again with empty headers. - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::string result = GetSpecificHeader(std::string(), tests[i].header_name); EXPECT_EQ(result, std::string()); } } TEST(NetUtilTest, CompliantHost) { + struct CompliantHostCase { + const char* host; + bool expected_output; + }; + const CompliantHostCase compliant_host_cases[] = { - {"", "", false}, - {"a", "", true}, - {"-", "", false}, - {".", "", false}, - {"9", "", true}, - {"9a", "", true}, - {"a.", "", true}, - {"a.a", "", true}, - {"9.a", "", true}, - {"a.9", "", true}, - {"_9a", "", false}, - {"-9a", "", false}, - {"-9a", "a", true}, - {"a.a9", "", true}, - {"a.-a9", "", false}, - {"a+9a", "", false}, - {"-a.a9", "", true}, - {"1-.a-b", "", true}, - {"1_.a-b", "", false}, - {"1-2.a_b", "", true}, - {"a.b.c.d.e", "", true}, - {"1.2.3.4.5", "", true}, - {"1.2.3.4.5.", "", true}, + {"", false}, + {"a", true}, + {"-", false}, + {".", false}, + {"9", true}, + {"9a", true}, + {"a.", true}, + {"a.a", true}, + {"9.a", true}, + {"a.9", true}, + {"_9a", false}, + {"-9a", false}, + {"a.a9", true}, + {"a.-a9", false}, + {"a+9a", false}, + {"-a.a9", true}, + {"1-.a-b", true}, + {"1_.a-b", false}, + {"1-2.a_b", true}, + {"a.b.c.d.e", true}, + {"1.2.3.4.5", true}, + {"1.2.3.4.5.", true}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(compliant_host_cases); ++i) { + for (size_t i = 0; i < arraysize(compliant_host_cases); ++i) { EXPECT_EQ(compliant_host_cases[i].expected_output, - IsCanonicalizedHostCompliant(compliant_host_cases[i].host, - compliant_host_cases[i].desired_tld)); + IsCanonicalizedHostCompliant(compliant_host_cases[i].host)); } } @@ -245,9 +254,20 @@ TEST(NetUtilTest, ParseHostAndPort) { { "[1080:0:0:0:8:800:200C:4171]:11", true, + "1080:0:0:0:8:800:200C:4171", + 11 + }, + { "[1080:0:0:0:8:800:200C:4171]", - 11, + true, + "1080:0:0:0:8:800:200C:4171", + -1 }, + + // Because no validation is done on the host, the following are accepted, + // even though they are invalid names. + {"]", true, "]", -1}, + {"::1", true, ":", 1}, // Invalid inputs: {"foo:bar", false, "", -1}, {"foo:", false, "", -1}, @@ -261,9 +281,11 @@ TEST(NetUtilTest, ParseHostAndPort) { {":password@host:80", false, "", -1}, {":password@host", false, "", -1}, {"@host", false, "", -1}, + {"[", false, "", -1}, + {"[]", false, "", -1}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::string host; int port; bool ok = ParseHostAndPort(tests[i].input, &host, &port); @@ -289,7 +311,7 @@ TEST(NetUtilTest, GetHostAndPort) { { GURL("http://[1::2]/x"), "[1::2]:80"}, { GURL("http://[::a]:33/x"), "[::a]:33"}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::string host_and_port = GetHostAndPort(tests[i].url); EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port); } @@ -307,7 +329,7 @@ TEST(NetUtilTest, GetHostAndOptionalPort) { { GURL("http://[1::2]/x"), "[1::2]"}, { GURL("http://[::a]:33/x"), "[::a]:33"}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { std::string host_and_port = GetHostAndOptionalPort(tests[i].url); EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port); } @@ -347,7 +369,7 @@ TEST(NetUtilTest, NetAddressToString_IPv4) { {{192, 168, 0, 1}, "192.168.0.1"}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { SockaddrStorage storage; MakeIPv4Address(tests[i].addr, 80, &storage); std::string result = NetAddressToString(storage.addr, storage.addr_len); @@ -365,7 +387,7 @@ TEST(NetUtilTest, NetAddressToString_IPv6) { "fedc:ba98:7654:3210:fedc:ba98:7654:3210"}, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { SockaddrStorage storage; MakeIPv6Address(tests[i].addr, 80, &storage); EXPECT_EQ(std::string(tests[i].result), @@ -441,7 +463,7 @@ TEST(NetUtilTest, SimplifyUrlForRequest) { "foobar://user:pass@google.com:80/sup?yo", }, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i, tests[i].input_url)); GURL input_url(GURL(tests[i].input_url)); @@ -454,12 +476,12 @@ TEST(NetUtilTest, SetExplicitlyAllowedPortsTest) { std::string invalid[] = { "1,2,a", "'1','2'", "1, 2, 3", "1 0,11,12" }; std::string valid[] = { "", "1", "1,2", "1,2,3", "10,11,12,13" }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(invalid); ++i) { + for (size_t i = 0; i < arraysize(invalid); ++i) { SetExplicitlyAllowedPorts(invalid[i]); EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts())); } - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid); ++i) { + for (size_t i = 0; i < arraysize(valid); ++i) { SetExplicitlyAllowedPorts(valid[i]); EXPECT_EQ(i, GetCountOfExplicitlyAllowedPorts()); } @@ -524,6 +546,31 @@ TEST(NetUtilTest, ConvertIPv4NumberToIPv6Number) { EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number)); } +TEST(NetUtilTest, ParseURLHostnameToNumber_FailParse) { + IPAddressNumber number; + + EXPECT_FALSE(ParseURLHostnameToNumber("bad value", &number)); + EXPECT_FALSE(ParseURLHostnameToNumber("bad:value", &number)); + EXPECT_FALSE(ParseURLHostnameToNumber(std::string(), &number)); + EXPECT_FALSE(ParseURLHostnameToNumber("192.168.0.1:30", &number)); + EXPECT_FALSE(ParseURLHostnameToNumber(" 192.168.0.1 ", &number)); + EXPECT_FALSE(ParseURLHostnameToNumber("::1", &number)); +} + +TEST(NetUtilTest, ParseURLHostnameToNumber_IPv4) { + IPAddressNumber number; + EXPECT_TRUE(ParseURLHostnameToNumber("192.168.0.1", &number)); + EXPECT_EQ("192,168,0,1", DumpIPNumber(number)); + EXPECT_EQ("192.168.0.1", IPAddressToString(number)); +} + +TEST(NetUtilTest, ParseURLHostnameToNumber_IPv6) { + IPAddressNumber number; + EXPECT_TRUE(ParseURLHostnameToNumber("[1:abcd::3:4:ff]", &number)); + EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number)); + EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number)); +} + TEST(NetUtilTest, IsIPv4Mapped) { IPAddressNumber ipv4_number; EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number)); @@ -647,7 +694,7 @@ TEST(NetUtilTest, IPNumberMatchesPrefix) { false }, }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + for (size_t i = 0; i < arraysize(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i, tests[i].cidr_literal, tests[i].ip_literal)); @@ -765,6 +812,261 @@ TEST(NetUtilTest, GetNetworkList) { } } +#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_NACL) + +char* CopyInterfaceName(const char* ifname, int ifname_size, char* output) { + EXPECT_LT(ifname_size, IF_NAMESIZE); + memcpy(output, ifname, ifname_size); + return output; +} + +static const char ifname_em1[] = "em1"; +char* GetInterfaceName(unsigned int interface_index, char* ifname) { + return CopyInterfaceName(ifname_em1, arraysize(ifname_em1), ifname); +} + +static const char ifname_vm[] = "vmnet"; +char* GetInterfaceNameVM(unsigned int interface_index, char* ifname) { + return CopyInterfaceName(ifname_vm, arraysize(ifname_vm), ifname); +} + +TEST(NetUtilTest, GetNetworkListTrimming) { + NetworkInterfaceList results; + ::base::hash_set<int> online_links; + net::internal::AddressTrackerLinux::AddressMap address_map; + + const unsigned char kIPv6LocalAddr[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + const unsigned char kIPv6Addr[] = + {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff, + 0xfe, 0xe5, 0x00, 0xc3}; + + IPAddressNumber ipv6_local_address( + kIPv6LocalAddr, kIPv6LocalAddr + arraysize(kIPv6LocalAddr)); + IPAddressNumber ipv6_address(kIPv6Addr, kIPv6Addr + arraysize(kIPv6Addr)); + + // Interface 1 is offline. + struct ifaddrmsg msg = { + AF_INET6, + 1, /* prefix length */ + IFA_F_TEMPORARY, /* address flags */ + 0, /* link scope */ + 1 /* link index */ + }; + + // Address of offline links should be ignored. + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceName)); + EXPECT_EQ(results.size(), 0ul); + + // Mark interface 1 online. + online_links.insert(1); + + // Local address should be trimmed out. + address_map.clear(); + ASSERT_TRUE( + address_map.insert(std::make_pair(ipv6_local_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceName)); + EXPECT_EQ(results.size(), 0ul); + + // vmware address should return by default. + address_map.clear(); + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceNameVM)); + EXPECT_EQ(results.size(), 1ul); + EXPECT_EQ(results[0].name, ifname_vm); + EXPECT_EQ(results[0].network_prefix, 1ul); + EXPECT_EQ(results[0].address, ipv6_address); + results.clear(); + + // vmware address should be trimmed out if policy specified so. + address_map.clear(); + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceNameVM)); + EXPECT_EQ(results.size(), 0ul); + results.clear(); + + // Addresses with banned attributes should be ignored. + address_map.clear(); + msg.ifa_flags = IFA_F_TENTATIVE; + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceName)); + EXPECT_EQ(results.size(), 0ul); + results.clear(); + + // Addresses with allowed attribute IFA_F_TEMPORARY should be returned and + // attributes should be translated correctly. + address_map.clear(); + msg.ifa_flags = IFA_F_TEMPORARY; + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceName)); + EXPECT_EQ(results.size(), 1ul); + EXPECT_EQ(results[0].name, ifname_em1); + EXPECT_EQ(results[0].network_prefix, 1ul); + EXPECT_EQ(results[0].address, ipv6_address); + EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY); + results.clear(); + + // Addresses with allowed attribute IFA_F_DEPRECATED should be returned and + // attributes should be translated correctly. + address_map.clear(); + msg.ifa_flags = IFA_F_DEPRECATED; + ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); + EXPECT_TRUE( + net::internal::GetNetworkListImpl(&results, + INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, + online_links, + address_map, + GetInterfaceName)); + EXPECT_EQ(results.size(), 1ul); + EXPECT_EQ(results[0].name, ifname_em1); + EXPECT_EQ(results[0].network_prefix, 1ul); + EXPECT_EQ(results[0].address, ipv6_address); + EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED); + results.clear(); +} + +#endif + +namespace { + +#if defined(OS_WIN) +bool read_int_or_bool(DWORD data_size, + PVOID data) { + switch (data_size) { + case 1: + return !!*reinterpret_cast<uint8*>(data); + case 4: + return !!*reinterpret_cast<uint32*>(data); + default: + LOG(FATAL) << "That is not a type I know!"; + return false; + } +} + +int GetWifiOptions() { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return -1; + + internal::WlanHandle client; + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client); + if (result != ERROR_SUCCESS) + return -1; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client.Get(), NULL, + &interface_list_ptr); + if (result != ERROR_SUCCESS) + return -1; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( + interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + DWORD data_size; + PVOID data; + int options = 0; + result = wlanapi.query_interface_func( + client.Get(), + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (!read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_DISABLE_SCAN; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + result = wlanapi.query_interface_func( + client.Get(), + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_MEDIA_STREAMING_MODE; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + // Just the the options from the first succesful + // interface. + return options; + } + + // No wifi interface found. + return -1; +} + +#else // OS_WIN + +int GetWifiOptions() { + // Not supported. + return -1; +} + +#endif // OS_WIN + +void TryChangeWifiOptions(int options) { + int previous_options = GetWifiOptions(); + scoped_ptr<ScopedWifiOptions> scoped_options = SetWifiOptions(options); + EXPECT_EQ(previous_options | options, GetWifiOptions()); + scoped_options.reset(); + EXPECT_EQ(previous_options, GetWifiOptions()); +} + +}; // namespace + +// Test SetWifiOptions(). +TEST(NetUtilTest, SetWifiOptionsTest) { + TryChangeWifiOptions(0); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN); + TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN | + WIFI_OPTIONS_MEDIA_STREAMING_MODE); +} + struct NonUniqueNameTestData { bool is_unique; const char* hostname; diff --git a/chromium/net/base/net_util_win.cc b/chromium/net/base/net_util_win.cc index cac92e39d54..7d146b91e51 100644 --- a/chromium/net/base/net_util_win.cc +++ b/chromium/net/base/net_util_win.cc @@ -22,67 +22,13 @@ #include "net/base/escape.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/net_util_win.h" #include "url/gurl.h" namespace net { namespace { -struct WlanApi { - typedef DWORD (WINAPI *WlanOpenHandleFunc)( - DWORD, VOID*, DWORD*, HANDLE*); - typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( - HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); - typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( - HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, - WLAN_OPCODE_VALUE_TYPE*); - typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); - typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); - - WlanApi() : initialized(false) { - // Use an absolute path to load the DLL to avoid DLL preloading attacks. - static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; - wchar_t path[MAX_PATH] = {0}; - ExpandEnvironmentStrings(kDLL, path, arraysize(path)); - module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!module) - return; - - open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( - ::GetProcAddress(module, "WlanOpenHandle")); - enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( - ::GetProcAddress(module, "WlanEnumInterfaces")); - query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( - ::GetProcAddress(module, "WlanQueryInterface")); - free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( - ::GetProcAddress(module, "WlanFreeMemory")); - close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( - ::GetProcAddress(module, "WlanCloseHandle")); - initialized = open_handle_func && enum_interfaces_func && - query_interface_func && free_memory_func && - close_handle_func; - } - - template <typename T> - DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { - HANDLE temp_handle; - DWORD result = open_handle_func(client_version, NULL, cur_version, - &temp_handle); - if (result != ERROR_SUCCESS) - return result; - handle->Set(temp_handle); - return ERROR_SUCCESS; - } - - HMODULE module; - WlanOpenHandleFunc open_handle_func; - WlanEnumInterfacesFunc enum_interfaces_func; - WlanQueryInterfaceFunc query_interface_func; - WlanFreeMemoryFunc free_memory_func; - WlanCloseHandleFunc close_handle_func; - bool initialized; -}; - // Converts Windows defined types to NetworkInterfaceType. NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { // Bail out for pre-Vista versions of Windows which are documented to give @@ -104,6 +50,43 @@ NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { } // namespace +namespace internal { + +base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = + LAZY_INSTANCE_INITIALIZER; + +WlanApi& WlanApi::GetInstance() { + return lazy_wlanapi.Get(); +} + +WlanApi::WlanApi() : initialized(false) { + // Use an absolute path to load the DLL to avoid DLL preloading attacks. + static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; + wchar_t path[MAX_PATH] = {0}; + ExpandEnvironmentStrings(kDLL, path, arraysize(path)); + module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!module) + return; + + open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( + ::GetProcAddress(module, "WlanOpenHandle")); + enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( + ::GetProcAddress(module, "WlanEnumInterfaces")); + query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( + ::GetProcAddress(module, "WlanQueryInterface")); + set_interface_func = reinterpret_cast<WlanSetInterfaceFunc>( + ::GetProcAddress(module, "WlanSetInterface")); + free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( + ::GetProcAddress(module, "WlanFreeMemory")); + close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( + ::GetProcAddress(module, "WlanCloseHandle")); + initialized = open_handle_func && enum_interfaces_func && + query_interface_func && set_interface_func && + free_memory_func && close_handle_func; +} + +} // namespace internal + bool GetNetworkList(NetworkInterfaceList* networks, int policy) { // GetAdaptersAddresses() may require IO operations. base::ThreadRestrictions::AssertIOAllowed(); @@ -190,20 +173,25 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { if (ipv6_valid_lifetime == 0 || ipv6_valid_lifetime > address->ValidLifetime) { ipv6_valid_lifetime = address->ValidLifetime; - ipv6_address.reset(new NetworkInterface(adapter->AdapterName, - base::SysWideToNativeMB(adapter->FriendlyName), - index, - GetNetworkInterfaceType(adapter->IfType), - endpoint.address(), - net_prefix)); + ipv6_address.reset(new NetworkInterface( + adapter->AdapterName, + base::SysWideToNativeMB(adapter->FriendlyName), + index, + GetNetworkInterfaceType(adapter->IfType), + endpoint.address(), + net_prefix, + IP_ADDRESS_ATTRIBUTE_NONE)); continue; } } networks->push_back( NetworkInterface(adapter->AdapterName, base::SysWideToNativeMB(adapter->FriendlyName), - index, GetNetworkInterfaceType(adapter->IfType), - endpoint.address(), net_prefix)); + index, + GetNetworkInterfaceType(adapter->IfType), + endpoint.address(), + net_prefix, + IP_ADDRESS_ATTRIBUTE_NONE)); } } } @@ -216,39 +204,11 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { } WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { - static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = - LAZY_INSTANCE_INITIALIZER; - - struct WlanApiHandleTraits { - typedef HANDLE Handle; - - static bool CloseHandle(HANDLE handle) { - return lazy_wlanapi.Get().close_handle_func(handle, NULL) == - ERROR_SUCCESS; - } - static bool IsHandleValid(HANDLE handle) { - return base::win::HandleTraits::IsHandleValid(handle); - } - static HANDLE NullHandle() { - return base::win::HandleTraits::NullHandle(); - } - }; - - typedef base::win::GenericScopedHandle< - WlanApiHandleTraits, - base::win::DummyVerifierTraits> WlanHandle; - - struct WlanApiDeleter { - inline void operator()(void* ptr) const { - lazy_wlanapi.Get().free_memory_func(ptr); - } - }; - - const WlanApi& wlanapi = lazy_wlanapi.Get(); + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); if (!wlanapi.initialized) return WIFI_PHY_LAYER_PROTOCOL_NONE; - WlanHandle client; + internal::WlanHandle client; DWORD cur_version = 0; const DWORD kMaxClientVersion = 2; DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client); @@ -256,10 +216,11 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { return WIFI_PHY_LAYER_PROTOCOL_NONE; WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; - result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); + result = wlanapi.enum_interfaces_func(client.Get(), NULL, + &interface_list_ptr); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_NONE; - scoped_ptr<WLAN_INTERFACE_INFO_LIST, WlanApiDeleter> interface_list( + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( interface_list_ptr); // Assume at most one connected wifi interface. @@ -279,11 +240,12 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { DWORD conn_info_size = 0; WLAN_OPCODE_VALUE_TYPE op_code; result = wlanapi.query_interface_func( - client, &info->InterfaceGuid, wlan_intf_opcode_current_connection, NULL, - &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), &op_code); + client.Get(), &info->InterfaceGuid, wlan_intf_opcode_current_connection, + NULL, &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), + &op_code); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; - scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( + scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, internal::WlanApiDeleter> conn_info( conn_info_ptr); switch (conn_info->wlanAssociationAttributes.dot11PhyType) { @@ -306,4 +268,60 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { } } +// Note: There is no need to explicitly set the options back +// as the OS will automatically set them back when the WlanHandle +// is closed. +class WifiOptionSetter : public ScopedWifiOptions { + public: + WifiOptionSetter(int options) { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return; + + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client_); + if (result != ERROR_SUCCESS) + return; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client_.Get(), NULL, + &interface_list_ptr); + if (result != ERROR_SUCCESS) + return; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> + interface_list(interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + if (options & WIFI_OPTIONS_DISABLE_SCAN) { + BOOL data = false; + wlanapi.set_interface_func(client_.Get(), + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + sizeof(data), + &data, + NULL); + } + if (options & WIFI_OPTIONS_MEDIA_STREAMING_MODE) { + BOOL data = true; + wlanapi.set_interface_func(client_.Get(), + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + sizeof(data), + &data, + NULL); + } + } + } + + private: + internal::WlanHandle client_; +}; + +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(new WifiOptionSetter(options)); +} + } // namespace net diff --git a/chromium/net/base/net_util_win.h b/chromium/net/base/net_util_win.h new file mode 100644 index 00000000000..afa888b1320 --- /dev/null +++ b/chromium/net/base/net_util_win.h @@ -0,0 +1,85 @@ +// Copyright (c) 2014 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 NET_BASE_NET_UTIL_WIN_H_ +#define NET_BASE_NET_UTIL_WIN_H_ + +// This file is only used to expose some of the internals +// of net_util_win.cc to tests. + +#include <wlanapi.h> + +#include "base/win/scoped_handle.h" +#include "net/base/net_export.h" + +namespace net { +namespace internal { + +struct NET_EXPORT WlanApi { + typedef DWORD (WINAPI *WlanOpenHandleFunc)( + DWORD, VOID*, DWORD*, HANDLE*); + typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( + HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); + typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, + WLAN_OPCODE_VALUE_TYPE*); + typedef DWORD (WINAPI *WlanSetInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, DWORD, const VOID*, VOID*); + typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); + typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); + + WlanApi(); + static WlanApi& GetInstance(); + + template <typename T> + DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { + HANDLE temp_handle; + DWORD result = open_handle_func(client_version, NULL, cur_version, + &temp_handle); + if (result != ERROR_SUCCESS) + return result; + handle->Set(temp_handle); + return ERROR_SUCCESS; + } + + HMODULE module; + WlanOpenHandleFunc open_handle_func; + WlanEnumInterfacesFunc enum_interfaces_func; + WlanQueryInterfaceFunc query_interface_func; + WlanSetInterfaceFunc set_interface_func; + WlanFreeMemoryFunc free_memory_func; + WlanCloseHandleFunc close_handle_func; + bool initialized; +}; + +struct WlanApiHandleTraits { + typedef HANDLE Handle; + + static bool CloseHandle(HANDLE handle) { + return WlanApi::GetInstance().close_handle_func(handle, NULL) == + ERROR_SUCCESS; + } + static bool IsHandleValid(HANDLE handle) { + return base::win::HandleTraits::IsHandleValid(handle); + } + static HANDLE NullHandle() { + return base::win::HandleTraits::NullHandle(); + } +}; + +typedef base::win::GenericScopedHandle< + WlanApiHandleTraits, + base::win::DummyVerifierTraits> WlanHandle; + +struct WlanApiDeleter { + inline void operator()(void* ptr) const { + WlanApi::GetInstance().free_memory_func(ptr); + } +}; + +} // namespace internal + +} // namespace net + +#endif // NET_BASE_NET_UTIL_WIN_H_ diff --git a/chromium/net/base/network_change_notifier.cc b/chromium/net/base/network_change_notifier.cc index c55be07d731..afd6b23d4fa 100644 --- a/chromium/net/base/network_change_notifier.cc +++ b/chromium/net/base/network_change_notifier.cc @@ -4,6 +4,8 @@ #include "net/base/network_change_notifier.h" +#include <limits> + #include "base/metrics/histogram.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -43,7 +45,7 @@ NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL; class MockNetworkChangeNotifier : public NetworkChangeNotifier { public: - virtual ConnectionType GetCurrentConnectionType() const OVERRIDE { + ConnectionType GetCurrentConnectionType() const override { return CONNECTION_UNKNOWN; } }; @@ -81,7 +83,7 @@ class HistogramWatcher NetworkChangeNotifier::AddNetworkChangeObserver(this); } - virtual ~HistogramWatcher() { + ~HistogramWatcher() override { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(g_network_change_notifier); NetworkChangeNotifier::RemoveConnectionTypeObserver(this); @@ -91,7 +93,7 @@ class HistogramWatcher } // NetworkChangeNotifier::IPAddressObserver implementation. - virtual void OnIPAddressChanged() OVERRIDE { + void OnIPAddressChanged() override { DCHECK(thread_checker_.CalledOnValidThread()); UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", SinceLast(&last_ip_address_change_)); @@ -101,8 +103,8 @@ class HistogramWatcher } // NetworkChangeNotifier::ConnectionTypeObserver implementation. - virtual void OnConnectionTypeChanged( - NetworkChangeNotifier::ConnectionType type) OVERRIDE { + void OnConnectionTypeChanged( + NetworkChangeNotifier::ConnectionType type) override { DCHECK(thread_checker_.CalledOnValidThread()); base::TimeTicks now = base::TimeTicks::Now(); int32 kilobytes_read = bytes_read_since_last_connection_change_ / 1000; @@ -262,15 +264,14 @@ class HistogramWatcher } // NetworkChangeNotifier::DNSObserver implementation. - virtual void OnDNSChanged() OVERRIDE { + void OnDNSChanged() override { DCHECK(thread_checker_.CalledOnValidThread()); UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", SinceLast(&last_dns_change_)); } // NetworkChangeNotifier::NetworkChangeObserver implementation. - virtual void OnNetworkChanged( - NetworkChangeNotifier::ConnectionType type) OVERRIDE { + void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override { DCHECK(thread_checker_.CalledOnValidThread()); if (type != NetworkChangeNotifier::CONNECTION_NONE) { UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange", @@ -422,7 +423,7 @@ class NetworkChangeNotifier::NetworkChangeCalculator AddIPAddressObserver(this); } - virtual ~NetworkChangeCalculator() { + ~NetworkChangeCalculator() override { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(g_network_change_notifier); RemoveConnectionTypeObserver(this); @@ -430,7 +431,7 @@ class NetworkChangeNotifier::NetworkChangeCalculator } // NetworkChangeNotifier::IPAddressObserver implementation. - virtual void OnIPAddressChanged() OVERRIDE { + void OnIPAddressChanged() override { DCHECK(thread_checker_.CalledOnValidThread()); base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_; @@ -439,7 +440,7 @@ class NetworkChangeNotifier::NetworkChangeCalculator } // NetworkChangeNotifier::ConnectionTypeObserver implementation. - virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE { + void OnConnectionTypeChanged(ConnectionType type) override { DCHECK(thread_checker_.CalledOnValidThread()); pending_connection_type_ = type; base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE @@ -535,6 +536,13 @@ NetworkChangeNotifier::GetConnectionType() { } // static +double NetworkChangeNotifier::GetMaxBandwidth() { + return g_network_change_notifier ? + g_network_change_notifier->GetCurrentMaxBandwidth() : + std::numeric_limits<double>::infinity(); +} + +// static void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) { if (!g_network_change_notifier) { *config = DnsConfig(); @@ -710,6 +718,32 @@ void NetworkChangeNotifier::RemoveNetworkChangeObserver( } } +// static +void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() { + if (g_network_change_notifier) + g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl(); +} + +// static +void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests( + ConnectionType type) { + if (g_network_change_notifier) + g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type); +} + +// static +void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + ConnectionType type) { + if (g_network_change_notifier) + g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type); +} + +// static +void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) { + if (g_network_change_notifier) + g_network_change_notifier->test_notifications_only_ = test_only; +} + NetworkChangeNotifier::NetworkChangeNotifier( const NetworkChangeCalculatorParams& params /*= NetworkChangeCalculatorParams()*/) @@ -726,7 +760,8 @@ NetworkChangeNotifier::NetworkChangeNotifier( new ObserverListThreadSafe<NetworkChangeObserver>( ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)), network_state_(new NetworkState()), - network_change_calculator_(new NetworkChangeCalculator(params)) { + network_change_calculator_(new NetworkChangeCalculator(params)), + test_notifications_only_(false) { DCHECK(!g_network_change_notifier); g_network_change_notifier = this; network_change_calculator_->Init(); @@ -739,19 +774,46 @@ NetworkChangeNotifier::GetAddressTrackerInternal() const { } #endif +double NetworkChangeNotifier::GetCurrentMaxBandwidth() const { + // This default implementation conforms to the NetInfo V3 specification but + // should be overridden to provide specific bandwidth data based on the + // platform. + if (GetCurrentConnectionType() == CONNECTION_NONE) + return 0.0; + return std::numeric_limits<double>::infinity(); +} + // static void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { - if (g_network_change_notifier) { - g_network_change_notifier->ip_address_observer_list_->Notify( - &IPAddressObserver::OnIPAddressChanged); + if (g_network_change_notifier && + !g_network_change_notifier->test_notifications_only_) { + g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl(); + } +} + +// static +void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { + if (g_network_change_notifier && + !g_network_change_notifier->test_notifications_only_) { + g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl( + GetConnectionType()); + } +} + +// static +void NetworkChangeNotifier::NotifyObserversOfNetworkChange( + ConnectionType type) { + if (g_network_change_notifier && + !g_network_change_notifier->test_notifications_only_) { + g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type); } } // static void NetworkChangeNotifier::NotifyObserversOfDNSChange() { - if (g_network_change_notifier) { - g_network_change_notifier->resolver_state_observer_list_->Notify( - &DNSObserver::OnDNSChanged); + if (g_network_change_notifier && + !g_network_change_notifier->test_notifications_only_) { + g_network_change_notifier->NotifyObserversOfDNSChangeImpl(); } } @@ -763,21 +825,24 @@ void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) { NotifyObserversOfDNSChange(); } -void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { - if (g_network_change_notifier) { - g_network_change_notifier->connection_type_observer_list_->Notify( - &ConnectionTypeObserver::OnConnectionTypeChanged, - GetConnectionType()); - } +void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() { + ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged); } -void NetworkChangeNotifier::NotifyObserversOfNetworkChange( +void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl( ConnectionType type) { - if (g_network_change_notifier) { - g_network_change_notifier->network_change_observer_list_->Notify( - &NetworkChangeObserver::OnNetworkChanged, - type); - } + connection_type_observer_list_->Notify( + &ConnectionTypeObserver::OnConnectionTypeChanged, type); +} + +void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl( + ConnectionType type) { + network_change_observer_list_->Notify( + &NetworkChangeObserver::OnNetworkChanged, type); +} + +void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() { + resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged); } NetworkChangeNotifier::DisableForTest::DisableForTest() diff --git a/chromium/net/base/network_change_notifier.h b/chromium/net/base/network_change_notifier.h index 6b801bc7c42..bdd2d181a1f 100644 --- a/chromium/net/base/network_change_notifier.h +++ b/chromium/net/base/network_change_notifier.h @@ -132,7 +132,7 @@ class NET_EXPORT NetworkChangeNotifier { // See the description of NetworkChangeNotifier::GetConnectionType(). // Implementations must be thread-safe. Implementations must also be - // cheap as this could be called (repeatedly) from the network thread. + // cheap as it is called often. virtual ConnectionType GetCurrentConnectionType() const = 0; // Replaces the default class factory instance of NetworkChangeNotifier class. @@ -159,6 +159,12 @@ class NET_EXPORT NetworkChangeNotifier { // the internet, the connection type is CONNECTION_WIFI. static ConnectionType GetConnectionType(); + // Returns a theoretical upper limit on download bandwidth, potentially based + // on underlying connection type, signal strength, or some other signal. The + // default mapping of connection type to maximum bandwidth is provided in the + // NetInfo spec: http://w3c.github.io/netinfo/. + static double GetMaxBandwidth(); + // Retrieve the last read DnsConfig. This could be expensive if the system has // a large HOSTS file. static void GetDnsConfig(DnsConfig* config); @@ -212,9 +218,15 @@ class NET_EXPORT NetworkChangeNotifier { static void RemoveNetworkChangeObserver(NetworkChangeObserver* observer); // Allow unit tests to trigger notifications. - static void NotifyObserversOfIPAddressChangeForTests() { - NotifyObserversOfIPAddressChange(); - } + static void NotifyObserversOfIPAddressChangeForTests(); + static void NotifyObserversOfConnectionTypeChangeForTests( + ConnectionType type); + static void NotifyObserversOfNetworkChangeForTests(ConnectionType type); + + // Enable or disable notifications from the host. After setting to true, be + // sure to pump the RunLoop until idle to finish any preexisting + // notifications. + static void SetTestNotificationsOnly(bool test_only); // Return a string equivalent to |type|. static const char* ConnectionTypeToString(ConnectionType type); @@ -289,6 +301,11 @@ class NET_EXPORT NetworkChangeNotifier { GetAddressTrackerInternal() const; #endif + // See the description of NetworkChangeNotifier::GetMaxBandwidth(). + // Implementations must be thread-safe. Implementations must also be + // cheap as it is called often. + virtual double GetCurrentMaxBandwidth() const; + // Broadcasts a notification to all registered observers. Note that this // happens asynchronously, even for observers on the current thread, even in // tests. @@ -309,6 +326,11 @@ class NET_EXPORT NetworkChangeNotifier { class NetworkState; class NetworkChangeCalculator; + void NotifyObserversOfIPAddressChangeImpl(); + void NotifyObserversOfConnectionTypeChangeImpl(ConnectionType type); + void NotifyObserversOfDNSChangeImpl(); + void NotifyObserversOfNetworkChangeImpl(ConnectionType type); + const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> > ip_address_observer_list_; const scoped_refptr<ObserverListThreadSafe<ConnectionTypeObserver> > @@ -327,6 +349,9 @@ class NET_EXPORT NetworkChangeNotifier { // Computes NetworkChange signal from IPAddress and ConnectionType signals. scoped_ptr<NetworkChangeCalculator> network_change_calculator_; + // Set true to disable non-test notifications (to prevent flakes in tests). + bool test_notifications_only_; + DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier); }; diff --git a/chromium/net/base/network_change_notifier_linux.cc b/chromium/net/base/network_change_notifier_linux.cc index 3fe96562c04..f77025a33d8 100644 --- a/chromium/net/base/network_change_notifier_linux.cc +++ b/chromium/net/base/network_change_notifier_linux.cc @@ -15,7 +15,7 @@ namespace net { class NetworkChangeNotifierLinux::Thread : public base::Thread { public: Thread(); - virtual ~Thread(); + ~Thread() override; // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType. // Safe to call from any thread. @@ -29,8 +29,8 @@ class NetworkChangeNotifierLinux::Thread : public base::Thread { protected: // base::Thread - virtual void Init() OVERRIDE; - virtual void CleanUp() OVERRIDE; + void Init() override; + void CleanUp() override; private: scoped_ptr<DnsConfigService> dns_config_service_; diff --git a/chromium/net/base/network_change_notifier_linux.h b/chromium/net/base/network_change_notifier_linux.h index a7080d9effb..5a0f6dff308 100644 --- a/chromium/net/base/network_change_notifier_linux.h +++ b/chromium/net/base/network_change_notifier_linux.h @@ -22,14 +22,14 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux class Thread; NetworkChangeNotifierLinux(); - virtual ~NetworkChangeNotifierLinux(); + ~NetworkChangeNotifierLinux() override; static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux(); // NetworkChangeNotifier: - virtual ConnectionType GetCurrentConnectionType() const OVERRIDE; + ConnectionType GetCurrentConnectionType() const override; - virtual const internal::AddressTrackerLinux* - GetAddressTrackerInternal() const OVERRIDE; + const internal::AddressTrackerLinux* GetAddressTrackerInternal() + const override; // The thread used to listen for notifications. This relays the notification // to the registered observers without posting back to the thread the object diff --git a/chromium/net/base/network_change_notifier_mac.cc b/chromium/net/base/network_change_notifier_mac.cc index 7fa97b48b61..14ec5542c51 100644 --- a/chromium/net/base/network_change_notifier_mac.cc +++ b/chromium/net/base/network_change_notifier_mac.cc @@ -43,18 +43,14 @@ class NetworkChangeNotifierMac::DnsConfigServiceThread : public base::Thread { public: DnsConfigServiceThread() : base::Thread("DnsConfigService") {} - virtual ~DnsConfigServiceThread() { - Stop(); - } + ~DnsConfigServiceThread() override { Stop(); } - virtual void Init() OVERRIDE { + void Init() override { service_ = DnsConfigService::CreateSystemService(); service_->WatchConfig(base::Bind(&NetworkChangeNotifier::SetDnsConfig)); } - virtual void CleanUp() OVERRIDE { - service_.reset(); - } + void CleanUp() override { service_.reset(); } private: scoped_ptr<DnsConfigService> service_; diff --git a/chromium/net/base/network_change_notifier_mac.h b/chromium/net/base/network_change_notifier_mac.h index 168ea1480b7..6f340872fc1 100644 --- a/chromium/net/base/network_change_notifier_mac.h +++ b/chromium/net/base/network_change_notifier_mac.h @@ -21,10 +21,10 @@ namespace net { class NetworkChangeNotifierMac: public NetworkChangeNotifier { public: NetworkChangeNotifierMac(); - virtual ~NetworkChangeNotifierMac(); + ~NetworkChangeNotifierMac() override; // NetworkChangeNotifier implementation: - virtual ConnectionType GetCurrentConnectionType() const OVERRIDE; + ConnectionType GetCurrentConnectionType() const override; // Forwarder just exists to keep the NetworkConfigWatcherMac API out of // NetworkChangeNotifierMac's public API. @@ -34,11 +34,10 @@ class NetworkChangeNotifierMac: public NetworkChangeNotifier { : net_config_watcher_(net_config_watcher) {} // NetworkConfigWatcherMac::Delegate implementation: - virtual void Init() OVERRIDE; - virtual void StartReachabilityNotifications() OVERRIDE; - virtual void SetDynamicStoreNotificationKeys( - SCDynamicStoreRef store) OVERRIDE; - virtual void OnNetworkConfigChange(CFArrayRef changed_keys) OVERRIDE; + void Init() override; + void StartReachabilityNotifications() override; + void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store) override; + void OnNetworkConfigChange(CFArrayRef changed_keys) override; private: NetworkChangeNotifierMac* const net_config_watcher_; diff --git a/chromium/net/base/network_change_notifier_unittest.cc b/chromium/net/base/network_change_notifier_unittest.cc new file mode 100644 index 00000000000..b8310fa5b7f --- /dev/null +++ b/chromium/net/base/network_change_notifier_unittest.cc @@ -0,0 +1,60 @@ +// Copyright (c) 2014 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 "net/base/network_change_notifier.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +// Note: This test is subject to the host's OS and network connection. This test +// is not future-proof. New standards will come about necessitating the need to +// alter the ranges of these tests. +TEST(NetworkChangeNotifierTest, NetMaxBandwidthRange) { + NetworkChangeNotifier::ConnectionType connection_type = + NetworkChangeNotifier::GetConnectionType(); + double max_bandwidth = NetworkChangeNotifier::GetMaxBandwidth(); + + // Always accept infinity as it's the default value if the bandwidth is + // unknown. + if (max_bandwidth == std::numeric_limits<double>::infinity()) { + EXPECT_NE(NetworkChangeNotifier::CONNECTION_NONE, connection_type); + return; + } + + switch (connection_type) { + case NetworkChangeNotifier::CONNECTION_UNKNOWN: + EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_ETHERNET: + EXPECT_GE(10.0, max_bandwidth); + EXPECT_LE(10000.0, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_WIFI: + EXPECT_GE(1.0, max_bandwidth); + EXPECT_LE(7000.0, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_2G: + EXPECT_GE(0.01, max_bandwidth); + EXPECT_LE(0.384, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_3G: + EXPECT_GE(2.0, max_bandwidth); + EXPECT_LE(42.0, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_4G: + EXPECT_GE(100.0, max_bandwidth); + EXPECT_LE(100.0, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_NONE: + EXPECT_EQ(0.0, max_bandwidth); + break; + case NetworkChangeNotifier::CONNECTION_BLUETOOTH: + EXPECT_GE(1.0, max_bandwidth); + EXPECT_LE(24.0, max_bandwidth); + break; + } +} + +} // namespace net diff --git a/chromium/net/base/network_change_notifier_win.cc b/chromium/net/base/network_change_notifier_win.cc index 77a72b0d693..1e6c51c7eb2 100644 --- a/chromium/net/base/network_change_notifier_win.cc +++ b/chromium/net/base/network_change_notifier_win.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/profiler/scoped_tracker.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "net/base/winsock_init.h" @@ -36,12 +37,12 @@ class NetworkChangeNotifierWin::DnsConfigServiceThread : public base::Thread { Stop(); } - virtual void Init() OVERRIDE { + virtual void Init() override { service_ = DnsConfigService::CreateSystemService(); service_->WatchConfig(base::Bind(&NetworkChangeNotifier::SetDnsConfig)); } - virtual void CleanUp() OVERRIDE { + virtual void CleanUp() override { service_.reset(); } @@ -218,6 +219,11 @@ void NetworkChangeNotifierWin::SetCurrentConnectionType( } void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "NetworkChangeNotifierWin_OnObjectSignaled")); + DCHECK(CalledOnValidThread()); DCHECK(is_watching_); is_watching_ = false; diff --git a/chromium/net/base/network_change_notifier_win.h b/chromium/net/base/network_change_notifier_win.h index 7b75c15dee3..9de1789f3d3 100644 --- a/chromium/net/base/network_change_notifier_win.h +++ b/chromium/net/base/network_change_notifier_win.h @@ -51,11 +51,11 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin friend class NetworkChangeNotifierWinTest; // NetworkChangeNotifier methods: - virtual ConnectionType GetCurrentConnectionType() const OVERRIDE; + virtual ConnectionType GetCurrentConnectionType() const override; // ObjectWatcher::Delegate methods: // Must only be called on the thread |this| was created on. - virtual void OnObjectSignaled(HANDLE object) OVERRIDE; + virtual void OnObjectSignaled(HANDLE object) override; // Does the actual work to determine the current connection type. // It is not thread safe, see crbug.com/324913. @@ -95,9 +95,6 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin // Number of times WatchForAddressChange has failed in a row. int sequential_failures_; - // Used for calling WatchForAddressChange again on failure. - base::WeakPtrFactory<NetworkChangeNotifierWin> weak_factory_; - // Thread on which we can run DnsConfigService. scoped_ptr<DnsConfigServiceThread> dns_config_service_thread_; @@ -110,6 +107,9 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin // Number of times polled to check if still offline. int offline_polls_; + // Used for calling WatchForAddressChange again on failure. + base::WeakPtrFactory<NetworkChangeNotifierWin> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierWin); }; diff --git a/chromium/net/base/network_change_notifier_win_unittest.cc b/chromium/net/base/network_change_notifier_win_unittest.cc index 979105f18b2..25873c37f20 100644 --- a/chromium/net/base/network_change_notifier_win_unittest.cc +++ b/chromium/net/base/network_change_notifier_win_unittest.cc @@ -32,7 +32,7 @@ class TestNetworkChangeNotifierWin : public NetworkChangeNotifierWin { // From NetworkChangeNotifierWin. virtual NetworkChangeNotifier::ConnectionType - RecomputeCurrentConnectionType() const OVERRIDE { + RecomputeCurrentConnectionType() const override { return NetworkChangeNotifier::CONNECTION_UNKNOWN; } diff --git a/chromium/net/base/network_config_watcher_mac.cc b/chromium/net/base/network_config_watcher_mac.cc index 8579a358391..bdf75c39ad2 100644 --- a/chromium/net/base/network_config_watcher_mac.cc +++ b/chromium/net/base/network_config_watcher_mac.cc @@ -31,12 +31,12 @@ void DynamicStoreCallback(SCDynamicStoreRef /* store */, class NetworkConfigWatcherMacThread : public base::Thread { public: NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate); - virtual ~NetworkConfigWatcherMacThread(); + ~NetworkConfigWatcherMacThread() override; protected: // base::Thread - virtual void Init() OVERRIDE; - virtual void CleanUp() OVERRIDE; + void Init() override; + void CleanUp() override; private: // The SystemConfiguration calls in this function can lead to contention early diff --git a/chromium/net/base/network_delegate.cc b/chromium/net/base/network_delegate.cc index d30a4ab4c88..9cad50a022b 100644 --- a/chromium/net/base/network_delegate.cc +++ b/chromium/net/base/network_delegate.cc @@ -5,8 +5,10 @@ #include "net/base/network_delegate.h" #include "base/logging.h" +#include "base/profiler/scoped_tracker.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" +#include "net/proxy/proxy_info.h" #include "net/url_request/url_request.h" namespace net { @@ -17,21 +19,71 @@ int NetworkDelegate::NotifyBeforeURLRequest( DCHECK(CalledOnValidThread()); DCHECK(request); DCHECK(!callback.is_null()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnBeforeURLRequest")); return OnBeforeURLRequest(request, callback, new_url); } +void NetworkDelegate::NotifyResolveProxy( + const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result) { + DCHECK(CalledOnValidThread()); + DCHECK(result); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnResolveProxy")); + OnResolveProxy(url, load_flags, proxy_service, result); +} + +void NetworkDelegate::NotifyProxyFallback( + const ProxyServer& bad_proxy, + int net_error) { + DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnProxyFallback")); + OnProxyFallback(bad_proxy, net_error); +} + int NetworkDelegate::NotifyBeforeSendHeaders( URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers) { DCHECK(CalledOnValidThread()); DCHECK(headers); DCHECK(!callback.is_null()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnBeforeSendHeaders")); return OnBeforeSendHeaders(request, callback, headers); } +void NetworkDelegate::NotifyBeforeSendProxyHeaders( + URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers) { + DCHECK(CalledOnValidThread()); + DCHECK(headers); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnBeforeSendProxyHeaders")); + OnBeforeSendProxyHeaders(request, proxy_info, headers); +} + void NetworkDelegate::NotifySendHeaders(URLRequest* request, const HttpRequestHeaders& headers) { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnSendHeaders")); OnSendHeaders(request, headers); } @@ -44,6 +96,10 @@ int NetworkDelegate::NotifyHeadersReceived( DCHECK(CalledOnValidThread()); DCHECK(original_response_headers); DCHECK(!callback.is_null()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnHeadersReceived")); return OnHeadersReceived(request, callback, original_response_headers, @@ -54,12 +110,20 @@ int NetworkDelegate::NotifyHeadersReceived( void NetworkDelegate::NotifyResponseStarted(URLRequest* request) { DCHECK(CalledOnValidThread()); DCHECK(request); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnResponseStarted")); OnResponseStarted(request); } void NetworkDelegate::NotifyRawBytesRead(const URLRequest& request, int bytes_read) { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnRawBytesRead")); OnRawBytesRead(request, bytes_read); } @@ -67,24 +131,39 @@ void NetworkDelegate::NotifyBeforeRedirect(URLRequest* request, const GURL& new_location) { DCHECK(CalledOnValidThread()); DCHECK(request); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnBeforeRedirect")); OnBeforeRedirect(request, new_location); } void NetworkDelegate::NotifyCompleted(URLRequest* request, bool started) { DCHECK(CalledOnValidThread()); DCHECK(request); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 NetworkDelegate::OnCompleted")); OnCompleted(request, started); } void NetworkDelegate::NotifyURLRequestDestroyed(URLRequest* request) { DCHECK(CalledOnValidThread()); DCHECK(request); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnURLRequestDestroyed")); OnURLRequestDestroyed(request); } void NetworkDelegate::NotifyPACScriptError(int line_number, const base::string16& error) { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnPACScriptError")); OnPACScriptError(line_number, error); } @@ -103,6 +182,10 @@ int NetworkDelegate::NotifyBeforeSocketStreamConnect( DCHECK(CalledOnValidThread()); DCHECK(socket); DCHECK(!callback.is_null()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnBeforeSocketStreamConnect")); return OnBeforeSocketStreamConnect(socket, callback); } @@ -110,6 +193,10 @@ bool NetworkDelegate::CanGetCookies(const URLRequest& request, const CookieList& cookie_list) { DCHECK(CalledOnValidThread()); DCHECK(!(request.load_flags() & net::LOAD_DO_NOT_SEND_COOKIES)); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCanGetCookies")); return OnCanGetCookies(request, cookie_list); } @@ -118,17 +205,29 @@ bool NetworkDelegate::CanSetCookie(const URLRequest& request, CookieOptions* options) { DCHECK(CalledOnValidThread()); DCHECK(!(request.load_flags() & net::LOAD_DO_NOT_SAVE_COOKIES)); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCanSetCookie")); return OnCanSetCookie(request, cookie_line, options); } bool NetworkDelegate::CanAccessFile(const URLRequest& request, const base::FilePath& path) const { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCanAccessFile")); return OnCanAccessFile(request, path); } bool NetworkDelegate::CanThrottleRequest(const URLRequest& request) const { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCanThrottleRequest")); return OnCanThrottleRequest(request); } @@ -136,21 +235,55 @@ bool NetworkDelegate::CanEnablePrivacyMode( const GURL& url, const GURL& first_party_for_cookies) const { DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCanEnablePrivacyMode")); return OnCanEnablePrivacyMode(url, first_party_for_cookies); } +bool NetworkDelegate::CancelURLRequestWithPolicyViolatingReferrerHeader( + const URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const { + DCHECK(CalledOnValidThread()); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 NetworkDelegate::OnCancelURLRequestWithPolicy...")); + return OnCancelURLRequestWithPolicyViolatingReferrerHeader( + request, target_url, referrer_url); +} + int NetworkDelegate::OnBeforeURLRequest(URLRequest* request, const CompletionCallback& callback, GURL* new_url) { return OK; } +void NetworkDelegate::OnResolveProxy( + const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result) { +} + +void NetworkDelegate::OnProxyFallback(const ProxyServer& bad_proxy, + int net_error) { +} + int NetworkDelegate::OnBeforeSendHeaders(URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers) { return OK; } +void NetworkDelegate::OnBeforeSendProxyHeaders( + URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers) { +} + void NetworkDelegate::OnSendHeaders(URLRequest* request, const HttpRequestHeaders& headers) { } @@ -225,4 +358,11 @@ int NetworkDelegate::OnBeforeSocketStreamConnect( return OK; } +bool NetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader( + const URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const { + return false; +} + } // namespace net diff --git a/chromium/net/base/network_delegate.h b/chromium/net/base/network_delegate.h index 4be320b9305..299989c9dab 100644 --- a/chromium/net/base/network_delegate.h +++ b/chromium/net/base/network_delegate.h @@ -35,6 +35,9 @@ namespace net { class CookieOptions; class HttpRequestHeaders; class HttpResponseHeaders; +class ProxyInfo; +class ProxyServer; +class ProxyService; class SocketStream; class URLRequest; @@ -60,9 +63,18 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { int NotifyBeforeURLRequest(URLRequest* request, const CompletionCallback& callback, GURL* new_url); + void NotifyResolveProxy(const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result); + void NotifyProxyFallback(const ProxyServer& bad_proxy, + int net_error); int NotifyBeforeSendHeaders(URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers); + void NotifyBeforeSendProxyHeaders(URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers); void NotifySendHeaders(URLRequest* request, const HttpRequestHeaders& headers); int NotifyHeadersReceived( @@ -96,6 +108,11 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { int NotifyBeforeSocketStreamConnect(SocketStream* socket, const CompletionCallback& callback); + bool CancelURLRequestWithPolicyViolatingReferrerHeader( + const URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const; + private: // This is the interface for subclasses of NetworkDelegate to implement. These // member functions will be called by the respective public notification @@ -117,6 +134,21 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { const CompletionCallback& callback, GURL* new_url); + // Called as the proxy is being resolved for |url|. Allows the delegate to + // override the proxy resolution decision made by ProxyService. The delegate + // may override the decision by modifying the ProxyInfo |result|. + virtual void OnResolveProxy(const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result); + + // Called when use of |bad_proxy| fails due to |net_error|. |net_error| is + // the network error encountered, if any, and OK if the fallback was + // for a reason other than a network error (e.g. the proxy service was + // explicitly directed to skip a proxy). + virtual void OnProxyFallback(const ProxyServer& bad_proxy, + int net_error); + // Called right before the HTTP headers are sent. Allows the delegate to // read/write |headers| before they get sent out. |callback| and |headers| are // valid only until OnCompleted or OnURLRequestDestroyed is called for this @@ -126,6 +158,13 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { const CompletionCallback& callback, HttpRequestHeaders* headers); + // Called after a proxy connection. Allows the delegate to read/write + // |headers| before they get sent out. |headers| is valid only until + // OnCompleted or OnURLRequestDestroyed is called for this request. + virtual void OnBeforeSendProxyHeaders(URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers); + // Called right before the HTTP request(s) are being sent to the network. // |headers| is only valid until OnCompleted or OnURLRequestDestroyed is // called for this request. @@ -236,6 +275,16 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { // See OnBeforeURLRequest for return value description. Returns OK by default. virtual int OnBeforeSocketStreamConnect( SocketStream* socket, const CompletionCallback& callback); + + // Called when the |referrer_url| for requesting |target_url| during handling + // of the |request| is does not comply with the referrer policy (e.g. a + // secure referrer for an insecure initial target). + // Returns true if the request should be cancelled. Otherwise, the referrer + // header is stripped from the request. + virtual bool OnCancelURLRequestWithPolicyViolatingReferrerHeader( + const URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const; }; } // namespace net diff --git a/chromium/net/base/openssl_private_key_store_android.cc b/chromium/net/base/openssl_private_key_store_android.cc index e9851077faa..56a63d23485 100644 --- a/chromium/net/base/openssl_private_key_store_android.cc +++ b/chromium/net/base/openssl_private_key_store_android.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" #include "net/android/network_library.h" namespace net { @@ -29,9 +30,8 @@ bool OpenSSLPrivateKeyStore::StoreKeyPair(const GURL& url, // in a format that is incompatible with what the platform expects. unsigned char* private_key = NULL; int private_len = 0; - crypto::ScopedOpenSSL< - PKCS8_PRIV_KEY_INFO, - PKCS8_PRIV_KEY_INFO_free> pkcs8(EVP_PKEY2PKCS8(pkey)); + crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type + pkcs8(EVP_PKEY2PKCS8(pkey)); if (pkcs8.get() != NULL) { private_len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &private_key); } diff --git a/chromium/net/base/openssl_private_key_store_memory.cc b/chromium/net/base/openssl_private_key_store_memory.cc index 0913e460bd2..4d6a287c2a7 100644 --- a/chromium/net/base/openssl_private_key_store_memory.cc +++ b/chromium/net/base/openssl_private_key_store_memory.cc @@ -36,7 +36,7 @@ class MemoryKeyPairStore { } bool StoreKeyPair(EVP_PKEY* pkey) { - CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_dup(pkey); base::AutoLock lock(lock_); keys_.push_back(pkey); return true; diff --git a/chromium/net/base/prioritized_dispatcher_unittest.cc b/chromium/net/base/prioritized_dispatcher_unittest.cc index 30360387ab1..40c74257ddc 100644 --- a/chromium/net/base/prioritized_dispatcher_unittest.cc +++ b/chromium/net/base/prioritized_dispatcher_unittest.cc @@ -117,7 +117,7 @@ class PrioritizedDispatcherTest : public testing::Test { } // PriorityDispatch::Job interface - virtual void Start() OVERRIDE { + void Start() override { EXPECT_FALSE(running_); handle_ = PrioritizedDispatcher::Handle(); running_ = true; diff --git a/chromium/net/base/priority_queue_unittest.cc b/chromium/net/base/priority_queue_unittest.cc index 8093319fddb..3e68acfb945 100644 --- a/chromium/net/base/priority_queue_unittest.cc +++ b/chromium/net/base/priority_queue_unittest.cc @@ -25,7 +25,7 @@ class PriorityQueueTest : public testing::Test { protected: PriorityQueueTest() : queue_(kNumPriorities) {} - virtual void SetUp() OVERRIDE { + void SetUp() override { CheckEmpty(); for (size_t i = 0; i < kNumElements; ++i) { EXPECT_EQ(i, queue_.size()); diff --git a/chromium/net/base/proxy_delegate.h b/chromium/net/base/proxy_delegate.h new file mode 100644 index 00000000000..7e00d0ca8c7 --- /dev/null +++ b/chromium/net/base/proxy_delegate.h @@ -0,0 +1,76 @@ +// Copyright 2014 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 NET_BASE_PROXY_DELEGATE_H_ +#define NET_BASE_PROXY_DELEGATE_H_ + +#include "base/macros.h" +#include "net/base/net_export.h" + +class GURL; + +namespace net { + +class HttpRequestHeaders; +class HttpResponseHeaders; +class HostPortPair; +class ProxyInfo; +class ProxyServer; +class ProxyService; +class URLRequest; + +// Delegate for setting up a connection. +class NET_EXPORT ProxyDelegate { + public: + ProxyDelegate() { + } + + virtual ~ProxyDelegate() { + } + + // Called as the proxy is being resolved for |url|. Allows the delegate to + // override the proxy resolution decision made by ProxyService. The delegate + // may override the decision by modifying the ProxyInfo |result|. + virtual void OnResolveProxy(const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result) = 0; + + // Called when use of |bad_proxy| fails due to |net_error|. |net_error| is + // the network error encountered, if any, and OK if the fallback was + // for a reason other than a network error (e.g. the proxy service was + // explicitly directed to skip a proxy). + virtual void OnFallback(const ProxyServer& bad_proxy, + int net_error) = 0; + + // Called after a proxy connection. Allows the delegate to read/write + // |headers| before they get sent out. |headers| is valid only until + // OnCompleted or OnURLRequestDestroyed is called for this request. + virtual void OnBeforeSendHeaders(URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers) = 0; + + // Called immediately before a proxy tunnel request is sent. + // Provides the embedder an opportunity to add extra request headers. + virtual void OnBeforeTunnelRequest(const HostPortPair& proxy_server, + HttpRequestHeaders* extra_headers) = 0; + + // Called when the connect attempt to a CONNECT proxy has completed. + virtual void OnTunnelConnectCompleted(const HostPortPair& endpoint, + const HostPortPair& proxy_server, + int net_error) = 0; + + // Called after the response headers for the tunnel request are received. + virtual void OnTunnelHeadersReceived( + const HostPortPair& origin, + const HostPortPair& proxy_server, + const HttpResponseHeaders& response_headers) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ProxyDelegate); +}; + +} + +#endif // NET_BASE_PROXY_DELEGATE_H_ diff --git a/chromium/net/base/registry_controlled_domains/OWNERS b/chromium/net/base/registry_controlled_domains/OWNERS index 9f8b1799602..2ba05a6168c 100644 --- a/chromium/net/base/registry_controlled_domains/OWNERS +++ b/chromium/net/base/registry_controlled_domains/OWNERS @@ -1,2 +1,3 @@ pam@chromium.org pkasting@chromium.org +rsleevi@chromium.org diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat index 4a8664322b8..111ee061c31 100644 --- a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat +++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat @@ -407,7 +407,7 @@ mil.bo tv.bo // br : http://registro.br/dominio/categoria.html -// Submitted by registry <fneves@registro.br> 2014-03-04 +// Submitted by registry <fneves@registro.br> 2014-08-11 br adm.br adv.br @@ -455,7 +455,7 @@ mil.br mp.br mus.br net.br -nom.br +*.nom.br not.br ntr.br odo.br @@ -821,7 +821,14 @@ gob.es edu.es // et : http://en.wikipedia.org/wiki/.et -*.et +et +com.et +gov.et +org.et +edu.et +biz.et +name.et +info.et // eu : http://en.wikipedia.org/wiki/.eu eu @@ -1594,7 +1601,7 @@ jobs // jp : http://en.wikipedia.org/wiki/.jp // http://jprs.co.jp/en/jpdomain.html -// Submitted by registry <info@jprs.jp> 2014-02-28 +// Submitted by registry <info@jprs.jp> 2014-10-30 jp // jp organizational type names ac.jp @@ -1606,7 +1613,7 @@ gr.jp lg.jp ne.jp or.jp -// jp preficture type names +// jp prefecture type names aichi.jp akita.jp aomori.jp @@ -1654,6 +1661,53 @@ wakayama.jp yamagata.jp yamaguchi.jp yamanashi.jp +栃木.jp +愛知.jp +愛媛.jp +兵庫.jp +熊本.jp +茨城.jp +北海道.jp +千葉.jp +和歌山.jp +長崎.jp +長野.jp +新潟.jp +青森.jp +静岡.jp +東京.jp +石川.jp +埼玉.jp +三重.jp +京都.jp +佐賀.jp +大分.jp +大阪.jp +奈良.jp +宮城.jp +宮崎.jp +富山.jp +山口.jp +山形.jp +山梨.jp +岩手.jp +岐阜.jp +岡山.jp +島根.jp +広島.jp +徳島.jp +沖縄.jp +滋賀.jp +神奈川.jp +福井.jp +福岡.jp +福島.jp +秋田.jp +群馬.jp +香川.jp +高知.jp +鳥取.jp +鹿児島.jp // jp geographic type names // http://jprs.jp/doc/rule/saisoku-1.html *.kawasaki.jp @@ -5252,27 +5306,30 @@ gop.pk gos.pk info.pk -// pl : http://www.dns.pl/english/ +// pl http://www.dns.pl/english/index.html +// confirmed on 26.09.2014 from Bogna Tchórzewska <partner@dns.pl> pl -// NASK functional domains (nask.pl / dns.pl) : http://www.dns.pl/english/dns-funk.html +com.pl +net.pl +org.pl +info.pl +waw.pl +gov.pl +// pl functional domains (http://www.dns.pl/english/index.html) aid.pl agro.pl atm.pl auto.pl biz.pl -com.pl edu.pl gmina.pl gsm.pl -info.pl mail.pl miasta.pl media.pl mil.pl -net.pl nieruchomosci.pl nom.pl -org.pl pc.pl powiat.pl priv.pl @@ -5288,12 +5345,7 @@ tm.pl tourism.pl travel.pl turystyka.pl -// ICM functional domains (icm.edu.pl) -6bone.pl -art.pl -mbone.pl // Government domains (administred by ippt.gov.pl) -gov.pl uw.gov.pl um.gov.pl ug.gov.pl @@ -5303,11 +5355,7 @@ so.gov.pl sr.gov.pl po.gov.pl pa.gov.pl -// other functional domains -ngo.pl -irc.pl -usenet.pl -// NASK geographical domains : http://www.dns.pl/english/dns-regiony.html +// pl regional domains (http://www.dns.pl/english/index.html) augustow.pl babia-gora.pl bedzin.pl @@ -5393,7 +5441,6 @@ rybnik.pl rzeszow.pl sanok.pl sejny.pl -siedlce.pl slask.pl slupsk.pl sosnowiec.pl @@ -5415,7 +5462,6 @@ ustka.pl walbrzych.pl warmia.pl warszawa.pl -waw.pl wegrow.pl wielun.pl wlocl.pl @@ -5428,18 +5474,6 @@ zagan.pl zarow.pl zgora.pl zgorzelec.pl -// TASK geographical domains (www.task.gda.pl/uslugi/dns) -gda.pl -gdansk.pl -gdynia.pl -med.pl -sopot.pl -// other geographical domains -gliwice.pl -krakow.pl -poznan.pl -wroc.pl -zakopane.pl // pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf pm @@ -5624,7 +5658,7 @@ mari.ru mari-el.ru marine.ru mordovia.ru -mosreg.ru +// mosreg.ru Bug 1090800 - removed at request of Aleksey Konstantinov <konstantinovav@mosreg.ru> msk.ru murmansk.ru nalchik.ru @@ -6008,11 +6042,35 @@ mil.to // Submitted by Ryan Sleevi <ryan.sleevi@gmail.com> 2014-01-03 tp -// tr : http://en.wikipedia.org/wiki/.tr -*.tr -!nic.tr -// Used by government in the TRNC -// http://en.wikipedia.org/wiki/.nc.tr +// subTLDs: https://www.nic.tr/forms/eng/policies.pdf +// and: https://www.nic.tr/forms/politikalar.pdf +// Submitted by <mehmetgurevin@gmail.com> 2014-07-19 +tr +com.tr +info.tr +biz.tr +net.tr +org.tr +web.tr +gen.tr +tv.tr +av.tr +dr.tr +bbs.tr +name.tr +tel.tr +gov.tr +bel.tr +pol.tr +mil.tr +k12.tr +edu.tr +kep.tr + +// Used by Northern Cyprus +nc.tr + +// Used by government agencies of Northern Cyprus gov.nc.tr // travel : http://en.wikipedia.org/wiki/.travel @@ -6287,7 +6345,7 @@ k12.mo.us k12.ms.us k12.mt.us k12.nc.us -k12.nd.us +// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso <trossow@nd.gov> k12.ne.us k12.nh.us k12.nj.us @@ -6312,7 +6370,6 @@ k12.wa.us k12.wi.us // k12.wv.us Bug 947705 - Removed at request of Verne Britton <verne@wvnet.edu> k12.wy.us - cc.ak.us cc.al.us cc.ar.us @@ -6368,7 +6425,6 @@ cc.wa.us cc.wi.us cc.wv.us cc.wy.us - lib.ak.us lib.al.us lib.ar.us @@ -6424,7 +6480,6 @@ lib.wa.us lib.wi.us // lib.wv.us Bug 941670 - Removed at request of Larry W Arnold <arnold@wvlc.lib.wv.us> lib.wy.us - // k12.ma.us contains school districts in Massachusetts. The 4LDs are // managed indepedently except for private (PVT), charter (CHTR) and // parochial (PAROCH) schools. Those are delegated dorectly to the @@ -6728,1269 +6783,1726 @@ xxx *.zw -// xn--80asehdb : 2013-07-14 CORE Association -онлайн +// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2014-11-03T18:02:06Z -// xn--80aswg : 2013-07-14 CORE Association -сайт +// abb : 2014-10-24 ABB Ltd +abb -// xn--ngbc5azd : 2013-07-14 International Domain Registry Pty. Ltd. -شبكة +// abbott : 2014-07-24 Abbott Laboratories, Inc. +abbott -// xn--unup4y : 2013-07-14 Spring Fields, LLC -游戏 +// abogado : 2014-04-24 Top Level Domain Holdings Limited +abogado -// xn--vhquv : 2013-08-28 Dash McCook, LLC -企业 +// academy : 2013-11-07 Half Oaks, LLC +academy -// camera : 2013-08-28 Atomic Maple, LLC -camera +// accenture : 2014-08-15 Accenture plc +accenture -// clothing : 2013-08-28 Steel Lake, LLC -clothing +// accountants : 2014-03-20 Knob Town, LLC +accountants -// lighting : 2013-08-28 John McCook, LLC -lighting +// active : 2014-05-01 The Active Network, Inc +active -// singles : 2013-08-28 Fern Madison, LLC -singles +// actor : 2013-12-12 United TLD Holdco Ltd. +actor -// ventures : 2013-08-28 Binky Lake, LLC -ventures +// adult : 2014-10-16 ICM Registry AD LLC +adult -// voyage : 2013-08-28 Ruby House, LLC -voyage +// afl : 2014-10-02 Australian Football League +afl -// guru : 2013-08-28 Pioneer Cypress, LLC -guru +// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa +africa -// holdings : 2013-08-28 John Madison, LLC -holdings +// agency : 2013-11-14 Steel Falls, LLC +agency -// equipment : 2013-08-28 Corn Station, LLC -equipment +// airforce : 2014-03-06 United TLD Holdco Ltd. +airforce -// bike : 2013-08-28 Grand Hollow, LLC -bike +// airtel : 2014-10-24 Bharti Airtel Limited +airtel -// estate : 2013-08-28 Trixy Park, LLC -estate +// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft +allfinanz -// tattoo : 2013-08-30 Uniregistry,Corp. -tattoo +// alsace : 2014-07-02 REGION D ALSACE +alsace -// xn--3ds443g : 2013-09-09 TLD Registry Limited -在线 +// amsterdam : 2014-07-24 Gemeente Amsterdam +amsterdam -// xn--fiq228c5hs : 2013-09-09 TLD Registry Limited -中文网 +// android : 2014-08-07 Charleston Road Registry Inc. +android -// land : 2013-09-10 Pine Moon, LLC -land +// aquarelle : 2014-07-24 Aquarelle.com +aquarelle -// plumbing : 2013-09-10 Spring Tigers, LLC -plumbing +// archi : 2014-02-06 STARTING DOT LIMITED +archi -// contractors : 2013-09-10 Magic Woods, LLC -contractors +// army : 2014-03-06 United TLD Holdco Ltd. +army -// sexy : 2013-09-11 Uniregistry,Corp. -sexy +// associates : 2014-03-06 Baxter Hill, LLC +associates -// menu : 2013-09-11 Wedding TLD2, LLC -menu +// attorney : 2014-03-20 +attorney -// xn--rhqv96g : 2013-09-11 Stable Tone Limited -世界 +// auction : 2014-03-20 +auction -// uno : 2013-09-11 Dot Latin, LLC -uno +// audio : 2014-03-20 Uniregistry, Corp. +audio -// gallery : 2013-09-13 Sugar House, LLC -gallery +// autos : 2014-01-09 DERAutos, LLC +autos -// technology : 2013-09-13 Auburn Falls -technology +// axa : 2013-12-19 AXA SA +axa -// xn--3bst00m : 2013-09-13 Eagle Horizon Limited -集团 +// band : 2014-06-12 +band -// reviews : 2013-09-13 Extra Cover, LLC -reviews +// bank : 2014-09-25 fTLD Registry Services LLC +bank -// guide : 2013-09-13 Snow Moon, LLC -guide +// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +bar -// xn--6qq986b3x1 : 2013-09-13 Tycoon Treasure Limited -我爱你 +// barcelona : 2014-07-24 Municipi de Barcelona +barcelona -// graphics : 2013-09-13 Over Madison, LLC -graphics +// bargains : 2013-11-14 Half Hallow, LLC +bargains -// construction : 2013-09-13 Fox Dynamite, LLC -construction +// bauhaus : 2014-04-17 Werkhaus GmbH +bauhaus -// onl : 2013-09-16 I-Registry Ltd. -onl +// bayern : 2014-01-23 Bayern Connect GmbH +bayern -// xn--q9jyb4c : 2013-09-17 Charleston Road Registry -みんな +// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A. +bbva -// diamonds : 2013-09-23 John Edge, LLC -diamonds +// bcn : 2014-07-24 Municipi de Barcelona +bcn -// kiwi : 2013-09-23 Dot Kiwi Limited -kiwi +// beer : 2014-01-09 Top Level Domain Holdings Limited +beer -// enterprises : 2013-09-23 Snow Oaks LLC -enterprises +// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG +berlin -// today : 2013-09-23 Pearl Woods, LLC -today +// best : 2013-12-19 BestTLD Pty Ltd +best -// futbol : 2013-09-23 Atomic Falls, LLC -futbol +// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited +bharti -// photography : 2013-09-23 Sugar Glen, LLC -photography +// bible : 2014-06-19 American Bible Society +bible -// tips : 2013-09-23 Corn Willow, LLC -tips +// bid : 2013-12-19 dot Bid Limited +bid -// directory : 2013-09-23 Extra Madison, LLC -directory +// bike : 2013-08-27 Grand Hollow, LLC +bike -// kitchen : 2013-09-23 Just Goodbye, LLC -kitchen +// bio : 2014-03-06 STARTING DOT LIMITED +bio -// xn--6frz82g : 2013-09-24 Afilias Limited -移动 +// black : 2014-01-16 Afilias Limited +black -// kim : 2013-09-24 Afilias Limited -kim +// blackfriday : 2014-01-16 Uniregistry, Corp. +blackfriday -// xn--cg4bki : 2013-09-27 Samsung SDS Co., LTD -삼성 +// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC +bloomberg -// monash : 2013-10-01 Monash University -monash +// blue : 2013-11-07 Afilias Limited +blue -// wed : 2013-10-02 Atgron, Inc. -wed +// bms : 2014-10-30 Bristol-Myers Squibb Company +bms -// pink : 2013-10-02 Afilias Limited -pink +// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +bmw -// ruhr : 2013-10-02 regiodot GmbH & Co. KG -ruhr +// bnl : 2014-07-24 Banca Nazionale del Lavoro +bnl -// buzz : 2013-10-03 DOTSTRATEGY CO. -buzz +// bnpparibas : 2014-05-29 BNP Paribas +bnpparibas -// careers : 2013-10-03 Wild Corner, LLC -careers +// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +bom -// shoes : 2013-10-03 Binky Galley, LLC -shoes +// bond : 2014-06-05 Bond University Limited +bond -// xn--4gbrim : 2013-10-07 Suhub Electronic Establishment -موقع +// boo : 2014-01-30 Charleston Road Registry Inc. +boo -// career : 2013-10-09 dotCareer, LLC -career +// boutique : 2013-11-14 Over Galley, LLC +boutique -// otsuka : 2013-10-11 Otsuka Holdings Co. Ltd. -otsuka +// brussels : 2014-02-06 DNS.be vzw +brussels -// xn--fiQ64b : 2013-10-14 CITIC Group Corporation -中信 +// budapest : 2013-11-21 Top Level Domain Holdings Limited +budapest -// gift : 2013-10-18 Uniregistry Corp. -gift +// build : 2013-11-07 Plan Bee LLC +build -// recipes : 2013-10-18 Grand Island, LLC -recipes +// builders : 2013-11-07 Atomic Madison, LLC +builders -// coffee : 2013-10-18 Trixy Cover, LLC -coffee +// business : 2013-11-07 Spring Cross, LLC +business -// luxury : 2013-10-18 Luxury Partners, LLC -luxury +// buzz : 2013-10-02 DOTSTRATEGY CO. +buzz -// domains : 2013-10-18 Sugar Cross, LLC -domains +// bzh : 2014-02-27 Association www.bzh +bzh -// photos : 2013-10-18 Sea Corner, LLC -photos +// cab : 2013-10-24 Half Sunset, LLC +cab -// limo : 2013-10-18 Hidden Frostbite, LLC -limo +// cal : 2014-07-24 Charleston Road Registry Inc. +cal -// viajes : 2013-10-18 Black Madison, LLC -viajes +// camera : 2013-08-27 Atomic Maple, LLC +camera -// wang : 2013-10-24 Zodiac Leo Limited -wang +// camp : 2013-11-07 Delta Dynamite, LLC +camp -// democrat : 2013-10-24 United TLD Holdco Ltd. -democrat +// cancerresearch : 2014-05-15 Australian Cancer Research Foundation +cancerresearch -// mango : 2013-10-25 PUNTO FA S.L. -mango +// canon : 2014-09-12 Canon Inc. +canon -// cab : 2013-10-25 Half Sunset, LLC -cab +// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +capetown -// support : 2013-10-25 Grand Orchard, LLC -support +// capital : 2014-03-06 Delta Mill, LLC +capital -// dance : 2013-10-25 United TLD Holdco Ltd. -dance +// caravan : 2013-12-12 Caravan International, Inc. +caravan -// nagoya : 2013-10-25 GMO Registry, Inc. -nagoya +// cards : 2013-12-05 Foggy Hollow, LLC +cards -// computer : 2013-10-25 Pine Mill, LLC -computer +// care : 2014-03-06 Goose Cross +care -// wien : 2013-10-28 punkt.wien GmbH -wien +// career : 2013-10-09 dotCareer LLC +career -// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG -berlin +// careers : 2013-10-02 Wild Corner, LLC +careers -// codes : 2013-10-31 Puff Willow, LLC -codes +// cartier : 2014-06-23 Richemont DNS Inc. +cartier -// email : 2013-10-31 Spring Madison, LLC -email +// casa : 2013-11-21 Top Level Domain Holdings Limited +casa -// xn--mgbab2bd : 2013-10-31 CORE Association -بازار +// cash : 2014-03-06 Delta Lake, LLC +cash -// repair : 2013-11-07 Lone Sunset, LLC -repair +// catering : 2013-12-05 New Falls. LLC +catering -// holiday : 2013-11-07 Goose Woods, LLC -holiday +// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +cba + +// cbn : 2014-08-22 The Christian Broadcasting Network, Inc. +cbn // center : 2013-11-07 Tin Mill, LLC center -// systems : 2013-11-07 Dash Cypress, LLC -systems - -// wiki : 2013-11-07 Top Level Design, LLC -wiki - // ceo : 2013-11-07 CEOTLD Pty Ltd ceo -// international : 2013-11-07 Wild Way, LLC -international +// cern : 2014-06-05 European Organization for Nuclear Research (\ +cern -// solar : 2013-11-07 Ruby Town, LLC -solar +// cfa : 2014-08-28 CFA Institute +cfa + +// channel : 2014-05-08 Charleston Road Registry Inc. +channel + +// cheap : 2013-11-14 Sand Cover, LLC +cheap + +// chloe : 2014-10-16 Richemont DNS Inc. +chloe + +// christmas : 2013-11-21 Uniregistry, Corp. +christmas + +// chrome : 2014-07-24 Charleston Road Registry Inc. +chrome + +// church : 2014-02-06 Holly Fileds, LLC +church + +// citic : 2014-01-09 CITIC Group Corporation +citic + +// city : 2014-05-29 Snow Sky, LLC +city + +// claims : 2014-03-20 Black Corner, LLC +claims + +// cleaning : 2013-12-05 Fox Shadow, LLC +cleaning + +// click : 2014-06-05 Uniregistry, Corp. +click + +// clinic : 2014-03-20 Goose Park, LLC +clinic + +// clothing : 2013-08-27 Steel Lake, LLC +clothing + +// club : 2013-11-08 .CLUB DOMAINS, LLC +club + +// coach : 2014-10-09 Koko Island, LLC +coach + +// codes : 2013-10-31 Puff Willow, LLC +codes + +// coffee : 2013-10-17 Trixy Cover, LLC +coffee + +// college : 2014-01-16 XYZ.COM LLC +college + +// cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH +cologne + +// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +commbank + +// community : 2013-12-05 Fox Orchard, LLC +community // company : 2013-11-07 Silver Avenue, LLC company -// education : 2013-11-07 Brice Way, LLC -education - -// training : 2013-11-07 Wild Willow, LLC -training +// computer : 2013-10-24 Pine Mill, LLC +computer -// academy : 2013-11-07 Half Oaks, LLC -academy +// condos : 2013-12-05 Pine House, LLC +condos -// marketing : 2013-11-07 Fern Pass, LLC -marketing +// construction : 2013-09-16 Fox Dynamite, LLC +construction -// florist : 2013-11-08 Half Cypress, LLC -florist +// consulting : 2013-12-05 +consulting -// solutions : 2013-11-07 Silver Cover, LLC -solutions +// contractors : 2013-09-10 Magic Woods, LLC +contractors -// build : 2013-11-07 Plan Bee LLC -build +// cooking : 2013-11-21 Top Level Domain Holdings Limited +cooking -// institute : 2013-11-07 Outer Maple, LLC -institute +// cool : 2013-11-14 Koko Lake, LLC +cool -// builders : 2013-11-07 Atomic Madison, LLC -builders +// corsica : 2014-09-25 Collectivité Territoriale de Corse +corsica -// red : 2013-11-07 Afilias Limited -red +// country : 2013-12-19 Top Level Domain Holdings Limited +country -// blue : 2013-11-07 Afilias Limited -blue +// credit : 2014-03-20 Snow Shadow, LLC +credit -// ninja : 2013-11-07 United TLD Holdco Ltd. -ninja +// creditcard : 2014-03-20 Binky Frostbite, LLC +creditcard -// business : 2013-11-07 Spring Cross, LLC -business +// cricket : 2014-10-09 dot Cricket Limited +cricket -// gal : 2013-11-07 Asociación puntoGAL -gal +// crown : 2014-10-24 Crown Equipment Corporation +crown -// social : 2013-11-07 United TLD Holdco Ltd. -social +// crs : 2014-04-03 Federated Co-operatives Limited +crs -// house : 2013-11-07 Sugar Park, LLC -house +// cruises : 2013-12-05 Spring Way, LLC +cruises -// camp : 2013-11-07 Delta Dynamite, LLC -camp +// csc : 2014-09-25 Alliance-One Services, Inc. +csc -// immobilien : 2013-11-07 United TLD Holdco Ltd. -immobilien +// cuisinella : 2014-04-03 SALM S.A.S. +cuisinella -// moda : 2013-11-07 United TLD Holdco Ltd. -moda +// cymru : 2014-05-08 Nominet UK +cymru -// glass : 2013-11-07 Black Cover, LLC -glass +// dabur : 2014-02-06 Dabur India Limited +dabur -// management : 2013-11-07 John Goodbye, LLC -management +// dad : 2014-01-23 Charleston Road Registry Inc. +dad -// kaufen : 2013-11-07 United TLD Holdco Ltd. -kaufen +// dance : 2013-10-24 United TLD Holdco Ltd. +dance -// farm : 2013-11-07 Just Maple, LLC -farm +// dating : 2013-12-05 Pine Fest, LLC +dating -// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center -公益 +// datsun : 2014-03-27 NISSAN MOTOR CO., LTD. +datsun -// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center -政务 +// day : 2014-01-30 Charleston Road Registry Inc. +day -// club : 2013-11-08 .CLUB DOMAINS, LLC -club +// deals : 2014-05-22 Sand Sunset, LLC +deals -// voting : 2013-11-13 Valuetainment Corp. -voting +// degree : 2014-03-06 +degree -// TOKYO : 2013-11-13 GMO Registry, Inc. -tokyo +// delivery : 2014-09-11 Steel Station, LLC +delivery -// moe : 2013-11-13 Interlink Co., Ltd. -moe +// dell : 2014-10-24 Dell Inc. +dell -// guitars : 2013-11-14 Uniregistry, Corp. -guitars +// democrat : 2013-10-24 United TLD Holdco Ltd. +democrat -// bargains : 2013-11-14 Half Hallow, LLC -bargains +// dental : 2014-03-20 Tin Birch, LLC +dental -// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry -组织机构 +// dentist : 2014-03-20 +dentist // desi : 2013-11-14 Desi Networks LLC desi -// cool : 2013-11-14 Koko Lake, LLC -cool +// dev : 2014-10-16 Charleston Road Registry Inc. +dev -// boutique : 2013-11-14 Over Galley, LLC -boutique +// diamonds : 2013-09-22 John Edge, LLC +diamonds -// pics : 2013-11-14 Uniregistry, Corp. -pics +// diet : 2014-06-26 Uniregistry, Corp. +diet -// xn--c1avg : 2013-11-14 Public Interest Registry -орг +// digital : 2014-03-06 Dash Park, LLC +digital -// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) -公司 +// direct : 2014-04-10 Half Trail, LLC +direct -// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) -网络 +// directory : 2013-09-20 Extra Madison, LLC +directory -// cheap : 2013-11-14 Sand Cover, LLC -cheap +// discount : 2014-03-06 Holly Hill, LLC +discount -// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. -广东 +// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd. +dnp -// photo : 2013-11-14 Uniregistry, Corp. -photo +// docs : 2014-10-16 Charleston Road Registry Inc. +docs -// network : 2013-11-14 Trixy Manor, LLC -network +// doha : 2014-09-18 Communications Regulatory Authority (CRA) +doha -// zone : 2013-11-14 Outer Falls, LLC -zone +// domains : 2013-10-17 Sugar Cross, LLC +domains -// xn--nqv7f : 2013-11-14 Public Interest Registry -机构 +// doosan : 2014-04-03 Doosan Corporation +doosan -// link : 2013-11-14 Uniregistry, Corp. -link +// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +durban -// QPON : 2013-11-14 dotCOOL, Inc. -qpon +// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +dvag -// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry -संगठन +// eat : 2014-01-23 Charleston Road Registry Inc. +eat -// agency : 2013-11-14 Steel Falls, LLC -agency +// education : 2013-11-07 Brice Way, LLC +education -// tienda : 2013-11-14 Victor Manor, LLC -tienda +// email : 2013-10-31 Spring Madison, LLC +email -// works : 2013-11-14 Little Dynamite, LLC -works +// emerck : 2014-04-03 Merck KGaA +emerck -// london : 2013-11-14 Dot London Domains Limited -london +// energy : 2014-09-11 Binky Birch, LLC +energy -// watch : 2013-11-14 Sand Shadow, LLC -watch +// engineer : 2014-03-06 United TLD Holdco Ltd. +engineer -// rocks : 2013-11-14 Ruby Moon, LLC -rocks +// engineering : 2014-03-06 Romeo Canyon +engineering -// SHIKSHA : 2013-11-14 Afilias Limited -shiksha +// enterprises : 2013-09-20 Snow Oaks, LLC +enterprises -// xn--d1acj3b : 2013-11-21 The Foundation for Network Initiatives “The Smart Internet” -дети +// equipment : 2013-08-27 Corn Station, LLC +equipment -// budapest : 2013-11-21 Top Level Domain Holdings Limited -budapest +// erni : 2014-04-03 ERNI Group Holding AG +erni -// nrw : 2013-11-21 Minds + Machines GmbH -nrw +// esq : 2014-05-08 Charleston Road Registry Inc. +esq -// VOTE : 2013-11-21 Monolith Registry LLC -vote +// estate : 2013-08-27 Trixy Park, LLC +estate -// fishing : 2013-11-21 Top Level Domain Holdings Limited -fishing +// eurovision : 2014-04-24 European Broadcasting Union (EBU) +eurovision + +// eus : 2013-12-12 Puntueus Fundazioa +eus + +// events : 2013-12-05 Pioneer Maple, LLC +events + +// everbank : 2014-05-15 EverBank +everbank + +// exchange : 2014-03-06 Spring Falls, LLC +exchange // expert : 2013-11-21 Magic Pass, LLC expert -// horse : 2013-11-21 Top Level Domain Holdings Limited -horse +// exposed : 2013-12-05 Victor Beach, LLC +exposed -// christmas : 2013-11-21 Uniregistry, Corp. -christmas +// fail : 2014-03-06 Atomic Pipe, LLC +fail -// cooking : 2013-11-21 Top Level Domain Holdings Limited -cooking +// fan : 2014-03-06 +fan -// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited -商城 +// farm : 2013-11-07 Just Maple, LLC +farm -// casa : 2013-11-21 Top Level Domain Holdings Limited -casa +// fashion : 2014-07-03 Top Level Domain Holdings Limited +fashion -// rich : 2013-11-21 I-REGISTRY Ltd., Niederlassung Deutschland -rich +// feedback : 2013-12-19 Top Level Spectrum, Inc. +feedback -// VOTO : 2013-11-21 Monolith Registry LLC -voto +// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +final -// tools : 2013-11-21 Pioneer North, LLC -tools +// finance : 2014-03-20 Cotton Cypress, LLC +finance -// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited -八卦 +// financial : 2014-03-06 Just Cover, LLC +financial -// praxi : 2013-12-05 Praxi S.p.A. -praxi +// firmdale : 2014-03-27 Firmdale Holdings Limited +firmdale -// events : 2013-12-05 Pioneer Maple, LLC -events +// fish : 2013-12-12 Fox Woods, LLC +fish + +// fishing : 2013-11-21 Top Level Domain Holdings Limited +fishing + +// fitness : 2014-03-06 Brice Orchard, LLC +fitness // flights : 2013-12-05 Fox Station, LLC flights -// report : 2013-12-05 Binky Glen, LLC -report +// florist : 2013-11-07 Half Cypress, LLC +florist -// partners : 2013-12-05 Magic Glen, LLC -partners +// flowers : 2014-10-09 Uniregistry, Corp. +flowers -// neustar : 2013-12-05 NeuStar, Inc. -neustar +// flsmidth : 2014-07-24 FLSmidth A/S +flsmidth -// rentals : 2013-12-05 Big Hollow,LLC -rentals +// fly : 2014-05-08 Charleston Road Registry Inc. +fly -// catering : 2013-12-05 New Falls. LLC -catering +// foo : 2014-01-23 Charleston Road Registry Inc. +foo -// community : 2013-12-05 Fox Orchard, LLC -community +// forsale : 2014-05-22 +forsale -// maison : 2013-12-05 Victor Frostbite, LLC -maison +// foundation : 2013-12-05 John Dale, LLC +foundation -// parts : 2013-12-05 Sea Goodbye, LLC -parts +// frl : 2014-05-15 FRLregistry B.V. +frl -// cleaning : 2013-12-05 Fox Shadow, LLC -cleaning +// frogans : 2013-12-19 OP3FT +frogans -// okinawa : 2013-12-05 BusinessRalliart inc. -okinawa +// fund : 2014-03-20 John Castle, LLC +fund -// foundation : 2013-12-05 John Dale, LLC -foundation +// furniture : 2014-03-20 Lone Fields, LLC +furniture -// properties : 2013-12-05 Big Pass, LLC -properties +// futbol : 2013-09-20 +futbol -// vacations : 2013-12-05 Atomic Tigers, LLC -vacations +// gal : 2013-11-07 Asociación puntoGAL +gal -// productions : 2013-12-05 Magic Birch, LLC -productions +// gallery : 2013-09-13 Sugar House, LLC +gallery -// industries : 2013-12-05 Outer House, LLC -industries +// garden : 2014-06-26 Top Level Domain Holdings Limited +garden + +// gbiz : 2014-07-17 Charleston Road Registry Inc. +gbiz + +// gdn : 2014-07-31 Joint Stock Company \ +gdn + +// gent : 2014-01-23 COMBELL GROUP NV/SA +gent + +// ggee : 2014-01-09 GMO Internet, Inc. +ggee + +// gift : 2013-10-17 Uniregistry, Corp. +gift + +// gifts : 2014-07-03 Goose Sky, LLC +gifts + +// gives : 2014-03-06 United TLD Holdco Ltd. +gives + +// glass : 2013-11-07 Black Cover, LLC +glass + +// gle : 2014-07-24 Charleston Road Registry Inc. +gle + +// global : 2014-04-17 Dot GLOBAL AS +global + +// globo : 2013-12-19 Globo Comunicação e Participações S.A +globo + +// gmail : 2014-05-01 Charleston Road Registry Inc. +gmail -// haus : 2013-12-05 Pixie Edge, LLC +// gmo : 2014-01-09 GMO Internet, Inc. +gmo + +// gmx : 2014-04-24 1&1 Mail & Media GmbH +gmx + +// google : 2014-07-24 Charleston Road Registry Inc. +google + +// gop : 2014-01-16 Republican State Leadership Committee, Inc. +gop + +// graphics : 2013-09-13 Over Madison, LLC +graphics + +// gratis : 2014-03-20 Pioneer Tigers, LLC +gratis + +// green : 2014-05-08 Afilias Limited +green + +// gripe : 2014-03-06 Corn Sunset, LLC +gripe + +// group : 2014-08-15 Romeo Town, LLC +group + +// guge : 2014-08-28 Charleston Road Registry Inc. +guge + +// guide : 2013-09-13 Snow Moon, LLC +guide + +// guitars : 2013-11-14 Uniregistry, Corp. +guitars + +// guru : 2013-08-27 Pioneer Cypress, LLC +guru + +// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH +hamburg + +// haus : 2013-12-05 haus -// vision : 2013-12-05 Koko Station, LLC -vision +// healthcare : 2014-06-12 Silver Glen, LLC +healthcare -// mormon : 2013-12-05 IRI Domain Management, LLC (""Applicant"") -mormon +// help : 2014-06-26 Uniregistry, Corp. +help -// cards : 2013-12-05 Foggy Hollow, LLC -cards +// here : 2014-02-06 Charleston Road Registry Inc. +here + +// hermes : 2014-07-10 HERMES INTERNATIONAL +hermes + +// hiphop : 2014-03-06 Uniregistry, Corp. +hiphop + +// hitachi : 2014-10-31 Hitachi, Ltd. +hitachi + +// hiv : 2014-03-13 dotHIV gemeinnuetziger e.V. +hiv + +// holdings : 2013-08-27 John Madison, LLC +holdings + +// holiday : 2013-11-07 Goose Woods, LLC +holiday + +// homes : 2014-01-09 DERHomes, LLC +homes + +// horse : 2013-11-21 Top Level Domain Holdings Limited +horse + +// host : 2014-04-17 DotHost Inc. +host + +// hosting : 2014-05-29 Uniregistry, Corp. +hosting + +// house : 2013-11-07 Sugar Park, LLC +house + +// how : 2014-01-23 Charleston Road Registry Inc. +how + +// hsbc : 2014-10-24 HSBC Holdings PLC +hsbc + +// ibm : 2014-07-31 International Business Machines Corporation +ibm + +// ice : 2014-10-30 IntercontinentalExchange, Inc. +ice + +// ifm : 2014-01-30 ifm electronic gmbh +ifm + +// iinet : 2014-07-03 Connect West Pty. Ltd. +iinet + +// immo : 2014-07-10 Auburn Bloom, LLC +immo + +// immobilien : 2013-11-07 United TLD Holdco Ltd. +immobilien + +// industries : 2013-12-05 Outer House, LLC +industries + +// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. +infiniti + +// ing : 2014-01-23 Charleston Road Registry Inc. +ing // ink : 2013-12-05 Top Level Design, LLC ink -// villas : 2013-12-05 New Sky, LLC -villas +// institute : 2013-11-07 Outer Maple, LLC +institute -// consulting : 2013-12-05 Pixie Station, LLC -consulting +// insure : 2014-03-20 Pioneer Willow, LLC +insure -// cruises : 2013-12-05 Spring Way, LLC -cruises +// international : 2013-11-07 Wild Way, LLC +international -// krd : 2013-12-05 KRG Department of Information Technology -krd +// investments : 2014-03-20 Holly Glen, LLC +investments -// xyz : 2013-12-05 XYZ.COM LLC -xyz +// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. +ipiranga -// dating : 2013-12-05 Pine Fest, LLC -dating +// irish : 2014-08-07 Dot-Irish LLC +irish -// exposed : 2013-12-05 Victor Beach, LLC -exposed +// ist : 2014-08-28 Istanbul Metropolitan Municipality +ist -// condos : 2013-12-05 Pine House, LLC -condos +// istanbul : 2014-08-28 Istanbul Metropolitan Municipality +istanbul -// eus : 2013-12-12 Puntueus Fundazioa -eus +// itau : 2014-10-02 Itau Unibanco Holding S.A. +itau -// Caravan : 2013-12-12 Caravan International, Inc. -caravan +// iwc : 2014-06-23 Richemont DNS Inc. +iwc -// actor : 2013-12-12 United TLD Holdco Ltd. -actor +// java : 2014-06-19 Oracle Corporation +java -// saarland : 2013-12-12 dotSaarland GmbH -saarland +// jetzt : 2014-01-09 New TLD Company AB +jetzt -// yokohama : 2013-12-12 GMO Registry, Inc. -yokohama +// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +joburg -// pub : 2013-12-12 United TLD Holdco Ltd. -pub +// jprs : 2014-09-18 Japan Registry Services Co., Ltd. +jprs -// xn--p1acf : 2013-12-12 Rusnames Limited -рус +// juegos : 2014-03-20 Uniregistry, Corp. +juegos -// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. -ren +// kaufen : 2013-11-07 United TLD Holdco Ltd. +kaufen -// fish : 2013-12-12 Fox Woods, LLC -fish +// kddi : 2014-09-12 KDDI CORPORATION +kddi -// BAR : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable -bar +// kim : 2013-09-23 Afilias Limited +kim -// DNP : 2013-12-13 Dai Nippon Printing Co., Ltd. -dnp +// kitchen : 2013-09-20 Just Goodbye, LLC +kitchen -// bid : 2013-12-19 dot Bid Limited -bid +// kiwi : 2013-09-20 DOT KIWI LIMITED +kiwi -// supply : 2013-12-19 Half Falls, LLC -supply +// koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH +koeln -// Miami : 2013-12-19 Top Level Domain Holdings Limited -miami +// krd : 2013-12-05 KRG Department of Information Technology +krd -// supplies : 2013-12-19 Atomic Fields, LLC -supplies +// kred : 2013-12-19 KredTLD Pty Ltd +kred -// quebec : 2013-12-19 PointQuébec Inc -quebec +// lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA +lacaixa -// MOSCOW : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) -moscow +// land : 2013-09-10 Pine Moon, LLC +land -// globo : 2013-12-19 Globo Comunicação e Participações S.A -globo +// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico +lat -// AXA : 2013-12-19 AXA SA -axa +// latrobe : 2014-06-16 La Trobe University +latrobe -// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) -москва +// lawyer : 2014-03-20 +lawyer -// xn--czrs0t : 2013-12-19 Wild Island, LLC -商店 +// lds : 2014-03-20 IRI Domain Management, LLC (\ +lds -// vodka : 2013-12-19 Top Level Domain Holdings Limited -vodka +// lease : 2014-03-06 Victor Trail, LLC +lease -// REST : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable -rest +// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc +leclerc -// frogans : 2013-12-19 OP3FT -frogans +// legal : 2014-10-16 Blue Falls, LLC +legal -// WTC : 2013-12-19 World Trade Centers Association, Inc. -wtc +// lgbt : 2014-05-08 Afilias Limited +lgbt -// rodeo : 2013-12-19 Top Level Domain Holdings Limited -rodeo +// liaison : 2014-10-02 Liaison Technologies, Incorporated +liaison -// sohu : 2013-12-19 Sohu.com Limited -sohu +// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +lidl -// BEST : 2013-12-19 BestTLD Pty Ltd -best +// life : 2014-02-06 Trixy Oaks, LLC +life -// country : 2013-12-19 Top Level Domain Holdings Limited -country +// lighting : 2013-08-27 John McCook, LLC +lighting -// KRED : 2013-12-19 KredTLD Pty Ltd -kred +// limited : 2014-03-06 Big Fest, LLC +limited -// feedback : 2013-12-19 Top Level Spectrum, Inc. -feedback +// limo : 2013-10-17 Hidden Frostbite, LLC +limo -// work : 2013-12-19 Top Level Domain Holdings Limited -work +// link : 2013-11-14 Uniregistry, Corp. +link + +// loans : 2014-03-20 June Woods, LLC +loans + +// london : 2013-11-14 Dot London Domains Limited +london + +// lotto : 2014-04-10 Afilias Limited +lotto + +// ltd : 2014-09-25 Over Corner, LLC +ltd + +// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA +ltda // luxe : 2014-01-09 Top Level Domain Holdings Limited luxe -// ryukyu : 2014-01-09 BusinessRalliart inc. -ryukyu +// luxury : 2013-10-17 Luxury Partners, LLC +luxury -// autos : 2014-01-09 DERAutos, LLC -autos +// madrid : 2014-05-01 Comunidad de Madrid +madrid -// homes : 2014-01-09 DERHomes, LLC -homes +// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) +maif -// jetzt : 2014-01-09 New TLD Company AB -jetzt +// maison : 2013-12-05 Victor Frostbite, LLC +maison -// yachts : 2014-01-09 DERYachts, LLC -yachts +// management : 2013-11-07 John Goodbye, LLC +management -// motorcycles : 2014-01-09 DERMotorcycles, LLC -motorcycles +// mango : 2013-10-24 PUNTO FA S.L. +mango + +// market : 2014-03-06 +market + +// marketing : 2013-11-07 Fern Pass, LLC +marketing + +// marriott : 2014-10-09 Marriott Worldwide Corporation +marriott + +// media : 2014-03-06 Grand Glen, LLC +media + +// meet : 2014-01-16 Afilias Limited +meet + +// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation +melbourne + +// meme : 2014-01-30 Charleston Road Registry Inc. +meme + +// memorial : 2014-10-16 Dog Beach, LLC +memorial + +// menu : 2013-09-11 Wedding TLD2, LLC +menu + +// miami : 2013-12-19 Top Level Domain Holdings Limited +miami // mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft mini -// ggee : 2014-01-09 GMO Internet, Inc. -ggee +// moda : 2013-11-07 United TLD Holdco Ltd. +moda -// beer : 2014-01-09 Top Level Domain Holdings Limited -beer +// moe : 2013-11-13 Interlink Co., Ltd. +moe -// xn--1qqw23a : 2014-01-13 Guangzhou YU Wei Information Technology Co., Ltd. -佛山 +// monash : 2013-09-30 Monash University +monash -// college : 2014-01-16 XYZ.COM LLC -college +// money : 2014-10-16 Outer McCook, LLC +money -// ovh : 2014-01-16 OVH SAS -ovh +// montblanc : 2014-06-23 Richemont DNS Inc. +montblanc -// meet : 2014-01-16 Afilias Limited -meet +// mormon : 2013-12-05 IRI Domain Management, LLC (\ +mormon -// xn--ses554g : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED -网址 +// mortgage : 2014-03-20 +mortgage -// gop : 2014-01-16 Republican State Leadership Committee, Inc. -gop +// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +moscow -// blackfriday : 2014-01-16 Uniregistry, Corp. -blackfriday +// motorcycles : 2014-01-09 DERMotorcycles, LLC +motorcycles -// lacaixa : 2014-01-16 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA -lacaixa +// mov : 2014-01-30 Charleston Road Registry Inc. +mov -// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED -商标 +// movistar : 2014-10-16 Telefónica S.A. +movistar -// vegas : 2014-01-16 Dot Vegas, Inc. -vegas +// nagoya : 2013-10-24 GMO Registry, Inc. +nagoya -// black : 2014-01-16 Afilias Limited -black +// navy : 2014-03-06 United TLD Holdco Ltd. +navy -// soy : 2014-01-23 Charleston Road Registry Inc. -soy +// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +netbank -// trade : 2014-01-23 Elite Registry Limited -trade +// network : 2013-11-14 Trixy Manor, LLC +network -// gent : 2014-01-23 COMBELL GROUP NV/SA -gent +// neustar : 2013-12-05 NeuStar, Inc. +neustar -// ing : 2014-01-23 Charleston Road Registry Inc. -ing +// new : 2014-01-30 Charleston Road Registry Inc. +new -// dad : 2014-01-23 Charleston Road Registry Inc. -dad +// nexus : 2014-07-24 Charleston Road Registry Inc. +nexus -// shriram : 2014-01-23 Shriram Capital Ltd. -shriram +// ngo : 2014-03-06 Public Interest Registry +ngo -// bayern : 2014-01-23 Bayern Connect GmbH -bayern +// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) +nhk -// scot : 2014-01-23 Dot Scot Registry Limited -scot +// ninja : 2013-11-07 United TLD Holdco Ltd. +ninja -// webcam : 2014-01-23 dot Webcam Limited -webcam +// nissan : 2014-03-27 NISSAN MOTOR CO., LTD. +nissan -// foo : 2014-01-23 Charleston Road Registry Inc. -foo +// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +nowruz -// eat : 2014-01-23 Charleston Road Registry Inc. -eat +// nra : 2014-05-22 NRA Holdings Company, INC. +nra -// nyc : 2014-01-23 The City of New York +// nrw : 2013-11-21 Minds + Machines GmbH +nrw + +// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION +ntt + +// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications nyc -// prod : 2014-01-23 Charleston Road Registry Inc. -prod +// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA +obi -// how : 2014-01-23 Charleston Road Registry Inc. -how +// okinawa : 2013-12-05 BusinessRalliart Inc. +okinawa -// day : 2014-01-30 Charleston Road Registry Inc. -day +// ong : 2014-03-06 Public Interest Registry +ong -// meme : 2014-01-30 Charleston Road Registry Inc. -meme +// onl : 2013-09-16 I-Registry Ltd. +onl -// mov : 2014-01-30 Charleston Road Registry Inc. -mov +// ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED +ooo + +// oracle : 2014-06-19 Oracle Corporation +oracle + +// organic : 2014-03-27 Afilias Limited +organic + +// osaka : 2014-09-04 Interlink Co., Ltd. +osaka + +// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. +otsuka + +// ovh : 2014-01-16 OVH SAS +ovh // paris : 2014-01-30 City of Paris paris -// boo : 2014-01-30 Charleston Road Registry Inc. -boo +// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +pars -// new : 2014-01-30 Charleston Road Registry Inc. -new +// partners : 2013-12-05 Magic Glen, LLC +partners -// ifm : 2014-01-30 ifm electronic gmbh -ifm +// parts : 2013-12-05 Sea Goodbye, LLC +parts -// life : 2014-02-06 Trixy Oaks, LLC -life +// party : 2014-09-11 Blue Sky Registry Limited +party -// archi : 2014-02-06 STARTING DOT LIMITED -archi +// pharmacy : 2014-06-19 National Association of Boards of Pharmacy +pharmacy -// spiegel : 2014-02-06 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG -spiegel +// photo : 2013-11-14 Uniregistry, Corp. +photo -// brussels : 2014-02-06 DNS.be vzw -brussels +// photography : 2013-09-20 Sugar Glen, LLC +photography -// church : 2014-02-06 Holly Fileds, LLC -church +// photos : 2013-10-17 Sea Corner, LLC +photos -// here : 2014-02-06 Charleston Road Registry Inc. -here +// physio : 2014-05-01 PhysBiz Pty Ltd +physio -// dabur : 2014-02-06 Dabur India Limited -dabur +// piaget : 2014-10-16 Richemont DNS Inc. +piaget -// vlaanderen : 2014-02-06 DNS.be vzw -vlaanderen +// pics : 2013-11-14 Uniregistry, Corp. +pics -// cologne : 2014-02-06 NetCologne Gesellschaft für Telekommunikation mbH -cologne +// pictet : 2014-06-26 Pictet Europe S.A. +pictet -// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd -手机 +// pictures : 2014-03-06 Foggy Sky, LLC +pictures -// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC -wme +// pink : 2013-10-01 Afilias Limited +pink -// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) -nhk +// pizza : 2014-06-26 Foggy Moon, LLC +pizza -// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION -suzuki +// place : 2014-04-24 Snow Galley, LLC +place -// whoswho : 2014-02-20 Who's Who Registry -whoswho +// plumbing : 2013-09-10 Spring Tigers, LLC +plumbing -// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB""\) -scb +// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +pohl -// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH -hamburg +// poker : 2014-07-03 Afilias Domains No. 5 Limited +poker -// services : 2014-02-27 Fox Castle, LLC -services +// porn : 2014-10-16 ICM Registry PN LLC +porn -// bzh : 2014-02-27 Association www.bzh -bzh +// praxi : 2013-12-05 Praxi S.p.A. +praxi -// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO -rio +// press : 2014-04-03 DotPress Inc. +press -// cash : 2014-03-07 Delta Lake, LLC -cash +// prod : 2014-01-23 Charleston Road Registry Inc. +prod -// gives : 2014-03-07 United TLD Holdco Ltd. -gives +// productions : 2013-12-05 Magic Birch, LLC +productions -// hiphop : 2014-03-07 Uniregistry, Corp. -hiphop +// prof : 2014-07-24 Charleston Road Registry Inc. +prof -// degree : 2014-03-07 Puff House, LLC -degree +// properties : 2013-12-05 Big Pass, LLC +properties -// digital : 2014-03-07 Dash Park, LLC -digital +// property : 2014-05-22 Uniregistry, Corp. +property -// rehab : 2014-03-07 United TLD Holdco Ltd. -rehab +// pub : 2013-12-12 United TLD Holdco Ltd. +pub -// wtf : 2014-03-07 Hidden Way, LLC -wtf +// qpon : 2013-11-14 dotCOOL, Inc. +qpon -// financial : 2014-03-07 Just Cover, LLC -financial +// quebec : 2013-12-19 PointQuébec Inc +quebec -// limited : 2014-03-07 Big Fest, LLC -limited +// realtor : 2014-05-29 Real Estate Domains LLC +realtor -// discount : 2014-03-07 Holly Hill, LLC -discount +// recipes : 2013-10-17 Grand Island, LLC +recipes -// fail : 2014-03-07 Atomic Pipe, LLC -fail +// red : 2013-11-07 Afilias Limited +red -// vet : 2014-03-07 Wild Dale, LLC -vet +// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. +redstone -// ngo : 2014-03-07 Public Interest Registry -ngo +// rehab : 2014-03-06 United TLD Holdco Ltd. +rehab -// fitness : 2014-03-07 Brice Orchard, LLC -fitness +// reise : 2014-03-13 dotreise GmbH +reise -// schule : 2014-03-07 Outer Moon, LLC -schule +// reisen : 2014-03-06 New Cypress, LLC +reisen -// navy : 2014-03-07 United TLD Holdco Ltd. -navy +// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. +reit -// bio : 2014-03-07 STARTING DOT LIMITED -bio +// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. +ren -// ong : 2014-03-07 Public Interest Registry -ong +// rentals : 2013-12-05 Big Hollow,LLC +rentals -// town : 2014-03-07 Koko Moon, LLC -town +// repair : 2013-11-07 Lone Sunset, LLC +repair -// toys : 2014-03-07 Pioneer Orchard, LLC -toys +// report : 2013-12-05 Binky Glen, LLC +report -// army : 2014-03-07 United TLD Holdco Ltd. -army +// republican : 2014-03-20 United TLD Holdco Ltd. +republican -// engineering : 2014-03-07 Romeo Canyon -engineering +// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +rest -// capital : 2014-03-07 Delta Mill, LLC -capital +// restaurant : 2014-07-03 Snow Avenue, LLC +restaurant -// exchange : 2014-03-07 Spring Falls, LLC -exchange +// reviews : 2013-09-13 +reviews -// fan : 2014-03-07 Goose Glen, LLC -fan +// rich : 2013-11-21 I-Registry Ltd. +rich -// market : 2014-03-07 Victor Way, LLC -market +// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO +rio -// media : 2014-03-07 Grand Glen, LLC -media +// rip : 2014-07-10 United TLD Holdco Ltd. +rip -// lease : 2014-03-07 Victor Trail, LLC -lease +// rocks : 2013-11-14 +rocks -// university : 2014-03-07 Little Station, LLC -university +// rodeo : 2013-12-19 Top Level Domain Holdings Limited +rodeo -// reisen : 2014-03-07 New Cypress, LLC -reisen +// rsvp : 2014-05-08 Charleston Road Registry Inc. +rsvp -// airforce : 2014-03-07 United TLD Holdco Ltd. -airforce +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr -// pictures : 2014-03-07 Foggy Sky, LLC -pictures +// ryukyu : 2014-01-09 BusinessRalliart Inc. +ryukyu -// gripe : 2014-03-07 Corn Sunset, LLC -gripe +// saarland : 2013-12-12 dotSaarland GmbH +saarland -// engineer : 2014-03-07 United TLD Holdco Ltd. -// CHROMIUM: Filed as bug http://bugzil.la/1024740 -engineer +// sale : 2014-10-16 Half Bloom, LLC +sale -// associates : 2014-03-07 Baxter Hill, LLC -associates +// samsung : 2014-04-03 SAMSUNG SDS CO., LTD +samsung -// xn--mxtq1m : 2014-03-07 Net-Chinese Co., Ltd. -政府 +// sanofi : 2014-10-09 Sanofi +sanofi -// williamhill : 2014-03-13 William Hill Organization Limited -williamhill +// sap : 2014-03-27 SAP AG +sap -// hiv : 2014-03-13 dotHIV gemeinnuetziger e.V. -hiv +// sarl : 2014-07-03 Delta Orchard, LLC +sarl + +// saxo : 2014-10-31 Saxo Bank A/S +saxo // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) sca -// reise : 2014-03-13 dotreise GmbH -reise +// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited (\ +scb -// accountants : 2014-03-20 Knob Town, LLC -accountants +// schmidt : 2014-04-03 SALM S.A.S. +schmidt -// clinic : 2014-03-20 Goose Park, LLC -clinic +// scholarships : 2014-04-24 Scholarships.com, LLC +scholarships -// versicherung : 2014-03-20 dotversicherung-registry GmbH -versicherung +// schule : 2014-03-06 Outer Moon, LLC +schule -// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. -top +// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +schwarz -// furniture : 2014-03-20 Lone Fields, LLC -furniture +// science : 2014-09-11 dot Science Limited +science -// dental : 2014-03-20 Tin Birch, LLC -dental +// scor : 2014-10-31 SCOR SE +scor -// fund : 2014-03-20 John Castle, LLC -fund +// scot : 2014-01-23 Dot Scot Registry Limited +scot -// creditcard : 2014-03-20 Binky Frostbite, LLC -creditcard +// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) +seat -// insure : 2014-03-20 Pioneer Willow, LLC -insure +// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. +sener -// audio : 2014-03-20 Uniregistry, Corp. -audio +// services : 2014-02-27 Fox Castle, LLC +services -// claims : 2014-03-20 Black Corner, LLC -claims +// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG +sew -// loans : 2014-03-20 June Woods, LLC -loans +// sexy : 2013-09-11 Uniregistry, Corp. +sexy -// auction : 2014-03-20 Sand Galley, LLC -auction +// sharp : 2014-05-01 Sharp Corporation +sharp -// attorney : 2014-03-20 Victor North, LLC -attorney +// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +shia -// finance : 2014-03-20 Cotton Cypress, LLC -finance +// shiksha : 2013-11-14 Afilias Limited +shiksha -// investments : 2014-03-20 Holly Glen, LLC -investments +// shoes : 2013-10-02 Binky Galley, LLC +shoes -// juegos : 2014-03-20 Uniregistry, Corp. -juegos +// shriram : 2014-01-23 Shriram Capital Ltd. +shriram -// dentist : 2014-03-20 Outer Lake, LLC -dentist +// singles : 2013-08-27 Fern Madison, LLC +singles -// lds : 2014-03-20 IRI Domain Management, LLC -lds +// sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch +sky -// lawyer : 2014-03-20 Atomic Station, LLC -lawyer +// social : 2013-11-07 United TLD Holdco Ltd. +social -// surgery : 2014-03-20 Tin Avenue, LLC +// software : 2014-03-20 +software + +// sohu : 2013-12-19 Sohu.com Limited +sohu + +// solar : 2013-11-07 Ruby Town, LLC +solar + +// solutions : 2013-11-07 Silver Cover, LLC +solutions + +// soy : 2014-01-23 Charleston Road Registry Inc. +soy + +// space : 2014-04-03 DotSpace Inc. +space + +// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG +spiegel + +// stc : 2014-10-09 Saudi Telecom Company +stc + +// stcgroup : 2014-10-09 Saudi Telecom Company +stcgroup + +// supplies : 2013-12-19 Atomic Fields, LLC +supplies + +// supply : 2013-12-19 Half Falls, LLC +supply + +// support : 2013-10-24 Grand Orchard, LLC +support + +// surf : 2014-01-09 Top Level Domain Holdings Limited +surf + +// surgery : 2014-03-20 Tin Avenue, LLC surgery -// gratis : 2014-03-20 Pioneer Tigers, LLC -gratis +// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION +suzuki -// software : 2014-03-20 Over Birch, LLC -software +// swiss : 2014-10-16 Swiss Confederation +swiss -// mortgage : 2014-03-20 Outer Gardens, LLC -mortgage +// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet +sydney -// republican : 2014-03-20 United TLD Holdco Ltd. -republican +// systems : 2013-11-07 Dash Cypress, LLC +systems -// credit : 2014-03-20 Snow Shadow, LLC -credit +// taipei : 2014-07-10 Taipei City Government +taipei -// tax : 2014-03-20 Storm Orchard, LLC +// tatar : 2014-04-24 Limited Liability Company \ +tatar + +// tattoo : 2013-08-30 Uniregistry, Corp. +tattoo + +// tax : 2014-03-20 Storm Orchard, LLC tax -// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa -africa +// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +tci -// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry -joburg +// technology : 2013-09-13 Auburn Falls +technology -// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry -durban +// telefonica : 2014-10-16 Telefónica S.A. +telefonica -// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry -capetown +// temasek : 2014-08-07 Temasek Holdings (Private) Limited +temasek -// sap : 2014-03-27 SAP AG -sap +// tienda : 2013-11-14 Victor Manor, LLC +tienda -// datsun : 2014-03-27 NISSAN MOTOR CO., LTD. -datsun +// tips : 2013-09-20 Corn Willow, LLC +tips -// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. -infiniti +// tirol : 2014-04-24 punkt Tirol GmbH +tirol -// firmdale : 2014-03-27 Firmdale Holdings Limited -firmdale +// today : 2013-09-20 Pearl Woods, LLC +today -// organic : 2014-03-27 Afilias Limited -organic +// tokyo : 2013-11-13 GMO Registry, Inc. +tokyo -// nissan : 2014-03-27 NISSAN MOTOR CO., LTD. -nissan +// tools : 2013-11-21 Pioneer North, LLC +tools -// website : 2014-04-03 DotWebsite Inc. -website +// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. +top -// space : 2014-04-03 DotSpace Inc. -space +// toshiba : 2014-04-10 TOSHIBA Corporation +toshiba -// schmidt : 2014-04-03 SALM S.A.S. -schmidt +// town : 2014-03-06 Koko Moon, LLC +town -// cuisinella : 2014-04-03 SALM S.A.S. -cuisinella +// toys : 2014-03-06 Pioneer Orchard, LLC +toys -// samsung : 2014-04-03 SAMSUNG SDS CO., LTD -samsung +// trade : 2014-01-23 Elite Registry Limited +trade -// crs : 2014-04-03 Federated Co operatives Limited -crs +// training : 2013-11-07 Wild Willow, LLC +training -// doosan : 2014-04-03 Doosan Corporation -doosan +// trust : 2014-10-16 +trust -// press : 2014-04-03 DotPress Inc. -press +// tui : 2014-07-03 TUI AG +tui -// emerck : 2014-04-03 Merck KGaA -emerck +// university : 2014-03-06 Little Station, LLC +university -// erni : 2014-04-03 ERNI Group Holding AG -erni +// uno : 2013-09-11 Dot Latin LLC +uno -// direct : 2014-04-10 Half Trail, LLC -direct +// uol : 2014-05-01 UBN INTERNET LTDA. +uol -// yandex : 2014-04-10 YANDEX, LLC -yandex +// vacations : 2013-12-05 Atomic Tigers, LLC +vacations -// lotto : 2014-04-10 Afilias Limited -lotto +// vegas : 2014-01-16 Dot Vegas, Inc. +vegas -// toshiba : 2014-04-10 TOSHIBA Corporation -toshiba +// ventures : 2013-08-27 Binky Lake, LLC +ventures -// bauhaus : 2014-04-17 Werkhaus GmbH -bauhaus +// versicherung : 2014-03-20 dotversicherung-registry GmbH +versicherung -// host : 2014-04-17 DotHost Inc. -host +// vet : 2014-03-06 +vet -// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA -ltda +// viajes : 2013-10-17 Black Madison, LLC +viajes -// global : 2014-04-17 Dot GLOBAL AS -global +// video : 2014-10-16 Lone Tigers, LLC +video -// abogado : 2014-04-24 Top Level Domain Holdings Limited -abogado +// villas : 2013-12-05 New Sky, LLC +villas -// place : 2014-04-24 Snow Galley, LLC -place +// virgin : 2014-09-25 Virgin Enterprises Limited +virgin -// tirol : 2014-04-24 punkt Tirol GmbH -tirol +// vision : 2013-12-05 Koko Station, LLC +vision -// gmx : 2014-04-24 1&1 Mail & Media GmbH -gmx +// vista : 2014-09-18 Vistaprint Limited +vista -// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" -tatar +// vistaprint : 2014-09-18 Vistaprint Limited +vistaprint -// scholarships : 2014-04-24 Scholarships.com, LLC -scholarships +// vlaanderen : 2014-02-06 DNS.be vzw +vlaanderen -// eurovision : 2014-04-24 European Broadcasting Union (EBU) -eurovision +// vodka : 2013-12-19 Top Level Domain Holdings Limited +vodka -// wedding : 2014-04-24 Top Level Domain Holdings Limited +// vote : 2013-11-21 Monolith Registry LLC +vote + +// voting : 2013-11-13 Valuetainment Corp. +voting + +// voto : 2013-11-21 Monolith Registry LLC +voto + +// voyage : 2013-08-27 Ruby House, LLC +voyage + +// wales : 2014-05-08 Nominet UK +wales + +// wang : 2013-10-24 Zodiac Leo Limited +wang + +// watch : 2013-11-14 Sand Shadow, LLC +watch + +// webcam : 2014-01-23 dot Webcam Limited +webcam + +// website : 2014-04-03 DotWebsite Inc. +website + +// wed : 2013-10-01 Atgron, Inc. +wed + +// wedding : 2014-04-24 Top Level Domain Holdings Limited wedding -// active : 2014-05-01 The Active Network, Inc -active +// whoswho : 2014-02-20 Who's Who Registry +whoswho -// madrid : 2014-05-01 Comunidad de Madrid -madrid +// wien : 2013-10-28 punkt.wien GmbH +wien -// youtube : 2014-05-01 Charleston Road Registry Inc. -youtube +// wiki : 2013-11-07 Top Level Design, LLC +wiki -// sharp : 2014-05-01 Sharp Corporation -sharp +// williamhill : 2014-03-13 William Hill Organization Limited +williamhill -// uol : 2014-05-01 UBN INTERNET LTDA. -uol +// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC +wme -// physio : 2014-05-01 PhysBiz Pty Ltd -physio +// work : 2013-12-19 Top Level Domain Holdings Limited +work -// gmail : 2014-05-01 Charleston Road Registry Inc. -gmail +// works : 2013-11-14 Little Dynamite, LLC +works -// channel : 2014-05-08 Charleston Road Registry Inc. -channel +// world : 2014-06-12 Bitter Fields, LLC +world -// fly : 2014-05-08 Charleston Road Registry Inc. -fly +// wtc : 2013-12-19 World Trade Centers Association, Inc. +wtc -// zip : 2014-05-08 Charleston Road Registry Inc. -zip +// wtf : 2014-03-06 Hidden Way, LLC +wtf -// esq : 2014-05-08 Charleston Road Registry Inc. -esq +// xerox : 2014-10-24 Xerox DNHC LLC +xerox -// rsvp : 2014-05-08 Charleston Road Registry Inc. -rsvp +// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. +佛山 -// wales : 2014-05-08 Nominet UK -wales +// xn--30rr7y : 2014-06-12 Excellent First Limited +慈善 -// cymru : 2014-05-08 Nominet UK -cymru +// xn--3bst00m : 2013-09-13 Eagle Horizon Limited +集团 -// green : 2014-05-08 Afilias Limited -green +// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED +在线 -// lgbt : 2014-05-08 Afilias Limited -lgbt +// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited +八卦 -// xn--hxt814e : 2014-05-15 Zodiac Libra Limited -网店 +// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment +موقع -// cancerresearch : 2014-05-15 Australian Cancer Research Foundation -cancerresearch +// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center +公益 -// everbank : 2014-05-15 EverBank -everbank +// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +公司 -// frl : 2014-05-15 FRLregistry B.V. -frl +// xn--6frz82g : 2013-09-23 Afilias Limited +移动 -// property : 2014-05-22 Uniregistry, Corp. -property +// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited +我爱你 -// forsale : 2014-05-22 Sea Oaks, LLC -forsale +// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +москва -// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) -seat +// xn--80asehdb : 2013-07-14 CORE Association +онлайн -// deals : 2014-05-22 Sand Sunset, LLC -deals +// xn--80aswg : 2013-07-14 CORE Association +сайт -// nra : 2014-05-22 NRA Holdings Company, INC. -nra +// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED +时尚 -// xn--fjq720a : 2014-05-22 Will Bloom, LLC +// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited +淡马锡 + +// xn--c1avg : 2013-11-14 Public Interest Registry +орг + +// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD +삼성 + +// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED +商标 + +// xn--czrs0t : 2013-12-19 Wild Island, LLC +商店 + +// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited +商城 + +// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” +дети + +// xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 +新闻 + +// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED +中文网 + +// xn--fiq64b : 2013-10-14 CITIC Group Corporation +中信 + +// xn--fjq720a : 2014-05-22 Will Bloom, LLC 娱乐 -// realtor : 2014-05-29 Real Estate Domains LLC -realtor +// xn--flw351e : 2014-07-31 Charleston Road Registry Inc. +谷歌 -// bnpparibas : 2014-05-29 BNP Paribas -bnpparibas +// xn--hxt814e : 2014-05-15 Zodiac Libra Limited +网店 -// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation -melbourne +// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry +संगठन -// hosting : 2014-05-29 Uniregistry, Corp. -hosting +// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +网络 + +// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd +手机 + +// xn--mgbab2bd : 2013-10-31 CORE Association +بازار + +// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +همراه + +// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd. +政府 + +// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd. +شبكة + +// xn--nqv7f : 2013-11-14 Public Interest Registry +机构 + +// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry +组织机构 + +// xn--p1acf : 2013-12-12 Rusnames Limited +рус + +// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc. +みんな + +// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc. +グーグル + +// xn--rhqv96g : 2013-09-11 Stable Tone Limited +世界 + +// xn--ses554g : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED +网址 + +// xn--unup4y : 2013-07-14 Spring Fields, LLC +游戏 + +// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberater + +// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberatung + +// xn--vhquv : 2013-08-27 Dash McCook, LLC +企业 + +// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. +信息 + +// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. +广东 + +// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center +政务 + +// xyz : 2013-12-05 XYZ.COM LLC +xyz -// yoga : 2014-05-29 Top Level Domain Holdings Limited +// yachts : 2014-01-09 DERYachts, LLC +yachts + +// yandex : 2014-04-10 YANDEX, LLC +yandex + +// yoga : 2014-05-29 Top Level Domain Holdings Limited yoga -// city : 2014-05-29 Snow Sky, LLC -city +// yokohama : 2013-12-12 GMO Registry, Inc. +yokohama -// bond : 2014-06-05 Bond University Limited -bond +// youtube : 2014-05-01 Charleston Road Registry Inc. +youtube -// click : 2014-06-05 Uniregistry, Corp. -click +// zip : 2014-05-08 Charleston Road Registry Inc. +zip -// cern : 2014-06-05 European Organization for Nuclear Research ("CERN") -cern +// zone : 2013-11-14 Outer Falls, LLC +zone // ===END ICANN DOMAINS=== // ===BEGIN PRIVATE DOMAINS=== @@ -8418,6 +8930,10 @@ global.prod.fastly.net // Submitted by Chris Raynor <chris@firebase.com> 2014-01-21 firebaseapp.com +// Flynn : https://flynn.io +// Submitted by Jonathan Rudenberg <jonathan@flynn.io> 2014-07-12 +flynnhub.com + // GitHub, Inc. // Submitted by Ben Toews <btoews@github.com> 2014-02-06 github.io @@ -8430,6 +8946,7 @@ ro.com // Google, Inc. // Submitted by Eduardo Vela <evn@google.com> 2012-10-24 appspot.com +blogspot.ae blogspot.be blogspot.bj blogspot.ca @@ -8444,6 +8961,7 @@ blogspot.com.ar blogspot.com.au blogspot.com.br blogspot.com.es +blogspot.com.tr blogspot.cv blogspot.cz blogspot.de @@ -8465,6 +8983,7 @@ blogspot.no blogspot.pt blogspot.re blogspot.ro +blogspot.ru blogspot.se blogspot.sg blogspot.sk @@ -8517,14 +9036,37 @@ operaunite.com // Submitted by Duarte Santos <domain-admin@outsystemscloud.com> 2014-03-11 outsystemscloud.com +// .pl domains (grandfathered) +art.pl +gliwice.pl +krakow.pl +poznan.pl +wroc.pl +zakopane.pl + // Red Hat, Inc. OpenShift : https://openshift.redhat.com/ // Submitted by Tim Kramer <tkramer@rhcloud.com> 2012-10-24 rhcloud.com +// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains +// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk> 2014-08-28 +service.gov.uk + // priv.at : http://www.nic.priv.at/ // Submitted by registry <lendl@nic.at> 2008-06-09 priv.at +// TASK geographical domains (www.task.gda.pl/uslugi/dns) +gda.pl +gdansk.pl +gdynia.pl +med.pl +sopot.pl + +// Yola : https://www.yola.com/ +// Submitted by Stefano Rivera <stefano@yola.com> 2014-07-09 +yolasite.com + // ZaNiC : http://www.za.net/ // Submitted by registry <hostmaster@nic.za.net> 2009-10-03 za.net diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf index 6bee195507e..b3b6afda455 100644 --- a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf +++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf @@ -19,7 +19,6 @@ struct DomainRule { 4.bg, 0 5.bg, 0 6.bg, 0 -6bone.pl, 0 7.bg, 0 8.bg, 0 9.bg, 0 @@ -31,6 +30,8 @@ aa.no, 0 aarborte.no, 0 ab.ca, 0 abashiri.hokkaido.jp, 0 +abb, 0 +abbott, 0 abeno.osaka.jp, 0 abiko.chiba.jp, 0 abira.hokkaido.jp, 0 @@ -74,6 +75,7 @@ ac.vn, 0 aca.pro, 0 academy, 0 academy.museum, 0 +accenture, 0 accident-investigation.aero, 0 accident-prevention.aero, 0 accountants, 0 @@ -86,6 +88,7 @@ ad, 0 ad.jp, 0 adachi.tokyo.jp, 0 adm.br, 0 +adult, 0 adult.ht, 0 adv.br, 0 adygeya.ru, 0 @@ -101,6 +104,7 @@ aerodrome.aero, 0 aeroport.fr, 0 af, 0 afjord.no, 0 +afl, 0 africa, 0 africa.com, 4 ag, 0 @@ -136,6 +140,7 @@ airforce, 0 airguard.museum, 0 airline.aero, 0 airport.aero, 0 +airtel, 0 airtraffic.aero, 0 aisai.aichi.jp, 0 aisho.shiga.jp, 0 @@ -169,6 +174,8 @@ alaska.museum, 0 alessandria.it, 0 alesund.no, 0 algard.no, 0 +allfinanz, 0 +alsace, 0 alstahaug.no, 0 alta.no, 0 altai.ru, 0 @@ -192,6 +199,7 @@ americanart.museum, 0 ami.ibaraki.jp, 0 amli.no, 0 amot.no, 0 +amsterdam, 0 amsterdam.museum, 0 amur.ru, 0 amursk.ru, 0 @@ -211,6 +219,7 @@ andria-barletta-trani.it, 0 andria-trani-barletta.it, 0 andriabarlettatrani.it, 0 andriatranibarletta.it, 0 +android, 0 anjo.aichi.jp, 0 annaka.gunma.jp, 0 annefrank.museum, 0 @@ -236,6 +245,7 @@ ap.it, 0 appspot.com, 4 aq, 0 aq.it, 0 +aquarelle, 0 aquarium.museum, 0 aquila.it, 0 ar, 0 @@ -269,7 +279,7 @@ art.do, 0 art.dz, 0 art.ht, 0 art.museum, 0 -art.pl, 0 +art.pl, 4 art.sn, 0 artanddesign.museum, 0 artcenter.museum, 0 @@ -366,6 +376,7 @@ auto.pl, 0 automotive.museum, 0 autos, 0 av.it, 0 +av.tr, 0 avellino.it, 0 averoy.no, 0 aviation.museum, 0 @@ -410,10 +421,13 @@ balsan.it, 0 balsfjord.no, 0 baltimore.museum, 0 bamble.no, 0 +band, 0 bandai.fukushima.jp, 0 bando.ibaraki.jp, 0 +bank, 0 bar, 0 bar.pro, 0 +barcelona, 0 barcelona.museum, 0 bardu.no, 0 bargains, 0 @@ -436,7 +450,10 @@ bauern.museum, 0 bauhaus, 0 bayern, 0 bb, 0 +bbs.tr, 0 +bbva, 0 bc.ca, 0 +bcn, 0 bd, 2 bd.se, 0 be, 0 @@ -447,6 +464,7 @@ bedzin.pl, 0 beeldengeluid.museum, 0 beer, 0 beiarn.no, 0 +bel.tr, 0 belau.pw, 0 belgorod.ru, 0 bellevue.museum, 0 @@ -470,11 +488,13 @@ bf, 0 bg, 0 bg.it, 0 bh, 0 +bharti, 0 bi, 0 bi.it, 0 bialowieza.pl, 0 bialystok.pl, 0 bibai.hokkaido.jp, 0 +bible, 0 bible.museum, 0 bid, 0 biei.hokkaido.jp, 0 @@ -499,6 +519,7 @@ biz, 0 biz.at, 4 biz.az, 0 biz.bb, 0 +biz.et, 0 biz.id, 0 biz.ki, 0 biz.mv, 0 @@ -508,6 +529,7 @@ biz.pk, 0 biz.pl, 0 biz.pr, 0 biz.tj, 0 +biz.tr, 0 biz.tt, 0 biz.vn, 0 bizen.okayama.jp, 0 @@ -524,6 +546,7 @@ blogdns.com, 4 blogdns.net, 4 blogdns.org, 4 blogsite.org, 4 +blogspot.ae, 4 blogspot.be, 4 blogspot.bj, 4 blogspot.ca, 4 @@ -538,6 +561,7 @@ blogspot.com.ar, 4 blogspot.com.au, 4 blogspot.com.br, 4 blogspot.com.es, 4 +blogspot.com.tr, 4 blogspot.cv, 4 blogspot.cz, 4 blogspot.de, 4 @@ -559,16 +583,21 @@ blogspot.no, 4 blogspot.pt, 4 blogspot.re, 4 blogspot.ro, 4 +blogspot.ru, 4 blogspot.se, 4 blogspot.sg, 4 blogspot.sk, 4 blogspot.td, 4 blogspot.tw, 4 +bloomberg, 0 blue, 0 bm, 0 bmd.br, 0 +bms, 0 +bmw, 0 bn, 2 bn.it, 0 +bnl, 0 bnpparibas, 0 bo, 0 bo.it, 0 @@ -581,6 +610,7 @@ boleslawiec.pl, 0 bologna.it, 0 bolt.hu, 0 bolzano.it, 0 +bom, 0 bomlo.no, 0 bond, 0 bonn.museum, 0 @@ -662,6 +692,7 @@ cab, 0 cadaques.museum, 0 cagliari.it, 0 cahcesuolo.no, 0 +cal, 0 cal.it, 0 calabria.it, 0 california.museum, 0 @@ -677,6 +708,7 @@ campobasso.it, 0 can.museum, 0 canada.museum, 0 cancerresearch, 0 +canon, 0 capebreton.museum, 0 capetown, 0 capital, 0 @@ -684,12 +716,14 @@ caravan, 0 carbonia-iglesias.it, 0 carboniaiglesias.it, 0 cards, 0 +care, 0 career, 0 careers, 0 cargo.aero, 0 carrara-massa.it, 0 carraramassa.it, 0 carrier.museum, 0 +cartier, 0 cartoonart.museum, 0 casa, 0 casadelamoneda.museum, 0 @@ -704,7 +738,9 @@ catanzaro.it, 0 catering, 0 catering.aero, 0 cb.it, 0 +cba, 0 cbg.ru, 0 +cbn, 0 cc, 0 cc.ak.us, 0 cc.al.us, 0 @@ -775,6 +811,7 @@ certification.aero, 0 cesena-forli.it, 0 cesenaforli.it, 0 cf, 0 +cfa, 0 cg, 0 ch, 0 ch.it, 0 @@ -823,6 +860,7 @@ chitose.hokkaido.jp, 0 chiyoda.gunma.jp, 0 chiyoda.tokyo.jp, 0 chizu.tottori.jp, 0 +chloe, 0 chocolate.museum, 0 chofu.tokyo.jp, 0 chonan.chiba.jp, 0 @@ -831,6 +869,7 @@ choshi.chiba.jp, 0 choyo.kumamoto.jp, 0 christiansburg.museum, 0 christmas, 0 +chrome, 0 chtr.k12.ma.us, 0 chukotka.ru, 0 chungbuk.kr, 0 @@ -849,6 +888,7 @@ cim.br, 0 cincinnati.museum, 0 cinema.museum, 0 circus.museum, 0 +citic, 0 city, 0 city.hu, 0 city.kawasaki.jp, 1 @@ -945,6 +985,7 @@ co.us, 0 co.uz, 0 co.ve, 0 co.vi, 0 +coach, 0 coal.museum, 0 coastaldefence.museum, 0 codes, 0 @@ -995,6 +1036,7 @@ com.ec, 0 com.ee, 0 com.eg, 0 com.es, 0 +com.et, 0 com.fr, 0 com.ge, 0 com.gh, 0 @@ -1074,6 +1116,7 @@ com.tj, 0 com.tm, 0 com.tn, 0 com.to, 0 +com.tr, 0 com.tt, 0 com.tw, 0 com.ua, 0 @@ -1086,6 +1129,7 @@ com.vi, 0 com.vn, 0 com.vu, 0 com.ws, 0 +commbank, 0 communication.museum, 0 communications.museum, 0 community, 0 @@ -1124,6 +1168,7 @@ coop.py, 0 coop.tt, 0 copenhagen.museum, 0 corporation.museum, 0 +corsica, 0 corvette.museum, 0 cosenza.it, 0 costume.museum, 0 @@ -1144,11 +1189,14 @@ creditcard, 0 cremona.it, 0 crew.aero, 0 cri.nz, 0 +cricket, 0 crimea.ua, 0 crotone.it, 0 +crown, 0 crs, 0 cruises, 0 cs.it, 0 +csc, 0 ct.it, 0 ct.us, 0 cu, 0 @@ -1204,6 +1252,8 @@ decorativearts.museum, 0 defense.tn, 0 degree, 0 delaware.museum, 0 +delivery, 0 +dell, 0 dell-ogliastra.it, 0 dellogliastra.it, 0 delmenhorst.museum, 0 @@ -1218,9 +1268,11 @@ desi, 0 design.aero, 0 design.museum, 0 detroit.museum, 0 +dev, 0 dgca.aero, 0 diamonds, 0 dielddanuorri.no, 0 +diet, 0 digital, 0 dinosaur.museum, 0 direct, 0 @@ -1245,9 +1297,11 @@ dnsdojo.com, 4 dnsdojo.net, 4 dnsdojo.org, 4 do, 0 +docs, 0 does-it.net, 4 doesntexist.com, 4 doesntexist.org, 4 +doha, 0 dolls.museum, 0 domains, 0 dominic.ua, 0 @@ -1264,6 +1318,7 @@ doshi.yamanashi.jp, 0 dovre.no, 0 dp.ua, 0 dr.na, 0 +dr.tr, 0 drammen.no, 0 drangedal.no, 0 dreamhosters.com, 4 @@ -1271,6 +1326,7 @@ drobak.no, 0 dudinka.ru, 0 durban, 0 durham.museum, 0 +dvag, 0 dvrdns.org, 4 dyn-o-saur.com, 4 dynalias.com, 4 @@ -1350,6 +1406,7 @@ edu.ec, 0 edu.ee, 0 edu.eg, 0 edu.es, 0 +edu.et, 0 edu.ge, 0 edu.gh, 0 edu.gi, 0 @@ -1422,6 +1479,7 @@ edu.sy, 0 edu.tj, 0 edu.tm, 0 edu.to, 0 +edu.tr, 0 edu.tt, 0 edu.tw, 0 edu.ua, 0 @@ -1473,6 +1531,7 @@ endofinternet.net, 4 endofinternet.org, 4 endoftheinternet.org, 4 enebakk.no, 0 +energy, 0 eng.br, 0 eng.pro, 0 engerdal.no, 0 @@ -1511,7 +1570,7 @@ est-mon-blogueur.com, 4 est.pr, 0 estate, 0 estate.museum, 0 -et, 2 +et, 0 etajima.hiroshima.jp, 0 etc.br, 0 ethnology.museum, 0 @@ -1552,6 +1611,7 @@ farmequipment.museum, 0 farmers.museum, 0 farmstead.museum, 0 farsund.no, 0 +fashion, 0 fauske.no, 0 fc.it, 0 fe.it, 0 @@ -1579,6 +1639,7 @@ film.hu, 0 film.museum, 0 fin.ec, 0 fin.tn, 0 +final, 0 finance, 0 financial, 0 fineart.museum, 0 @@ -1618,7 +1679,10 @@ florence.it, 0 florida.museum, 0 florist, 0 floro.no, 0 +flowers, 0 +flsmidth, 0 fly, 0 +flynnhub.com, 4 fm, 0 fm.br, 0 fm.it, 0 @@ -1816,6 +1880,7 @@ gamo.shiga.jp, 0 gamvik.no, 0 gangaviika.no, 0 gangwon.kr, 0 +garden, 0 garden.museum, 0 gateway.museum, 0 gaular.no, 0 @@ -1823,12 +1888,14 @@ gausdal.no, 0 gb, 0 gb.com, 4 gb.net, 4 +gbiz, 0 gc.ca, 0 gd, 0 gd.cn, 0 -gda.pl, 0 -gdansk.pl, 0 -gdynia.pl, 0 +gda.pl, 4 +gdansk.pl, 4 +gdn, 0 +gdynia.pl, 4 ge, 0 ge.it, 0 geek.nz, 0 @@ -1837,6 +1904,7 @@ geisei.kochi.jp, 0 gemological.museum, 0 gen.in, 0 gen.nz, 0 +gen.tr, 0 genkai.saga.jp, 0 genoa.it, 0 genova.it, 0 @@ -1855,6 +1923,7 @@ gi, 0 giehtavuoatna.no, 0 giessen.museum, 0 gift, 0 +gifts, 0 gifu.gifu.jp, 0 gifu.jp, 0 gildeskal.no, 0 @@ -1874,8 +1943,9 @@ gl, 0 glas.museum, 0 glass, 0 glass.museum, 0 +gle, 0 gliding.aero, 0 -gliwice.pl, 0 +gliwice.pl, 4 global, 0 global.prod.fastly.net, 4 global.ssl.fastly.net, 4 @@ -1885,6 +1955,7 @@ gloppen.no, 0 gm, 0 gmail, 0 gmina.pl, 0 +gmo, 0 gmx, 0 gn, 0 gniezno.pl, 0 @@ -1922,6 +1993,7 @@ gokase.miyazaki.jp, 0 gol.no, 0 gon.pk, 0 gonohe.aomori.jp, 0 +google, 0 googleapis.com, 4 googlecode.com, 4 gop, 0 @@ -1979,6 +2051,7 @@ gov.dz, 0 gov.ec, 0 gov.ee, 0 gov.eg, 0 +gov.et, 0 gov.ge, 0 gov.gh, 0 gov.gi, 0 @@ -2051,6 +2124,7 @@ gov.tl, 0 gov.tm, 0 gov.tn, 0 gov.to, 0 +gov.tr, 0 gov.tt, 0 gov.tw, 0 gov.ua, 0 @@ -2085,6 +2159,7 @@ groks-this.info, 4 grong.no, 0 grosseto.it, 0 groundhandling.aero, 0 +group, 0 group.aero, 0 grozny.ru, 0 grp.lk, 0 @@ -2118,6 +2193,7 @@ gu, 2 gu.us, 0 gub.uy, 0 guernsey.museum, 0 +guge, 0 guide, 0 guitars, 0 gujo.gifu.jp, 0 @@ -2215,10 +2291,12 @@ he.cn, 0 health.museum, 0 health.nz, 0 health.vn, 0 +healthcare, 0 heguri.nara.jp, 0 heimatunduhren.museum, 0 hekinan.aichi.jp, 0 hellas.museum, 0 +help, 0 helsinki.museum, 0 hembygdsforbund.museum, 0 hemne.no, 0 @@ -2228,6 +2306,7 @@ herad.no, 0 here, 0 here-for-more.info, 4 heritage.museum, 0 +hermes, 0 herokuapp.com, 4 herokussl.com, 4 heroy.more-og-romsdal.no, 0 @@ -2306,6 +2385,7 @@ historisches.museum, 0 history.museum, 0 historyofscience.museum, 0 hita.oita.jp, 0 +hitachi, 0 hitachi.ibaraki.jp, 0 hitachinaka.ibaraki.jp, 0 hitachiomiya.ibaraki.jp, 0 @@ -2378,6 +2458,7 @@ hoyanger.no, 0 hoylandet.no, 0 hr, 0 hs.kr, 0 +hsbc, 0 ht, 0 hu, 0 hu.com, 4 @@ -2401,6 +2482,8 @@ ibaraki.jp, 0 ibaraki.osaka.jp, 0 ibestad.no, 0 ibigawa.gifu.jp, 0 +ibm, 0 +ice, 0 ichiba.tokushima.jp, 0 ichihara.chiba.jp, 0 ichikai.tochigi.jp, 0 @@ -2430,6 +2513,7 @@ iheya.okinawa.jp, 0 iida.nagano.jp, 0 iide.yamagata.jp, 0 iijima.nagano.jp, 0 +iinet, 0 iitate.fukushima.jp, 0 iiyama.nagano.jp, 0 iizuka.fukuoka.jp, 0 @@ -2458,6 +2542,7 @@ imakane.hokkaido.jp, 0 imari.saga.jp, 0 imb.br, 0 imizu.toyama.jp, 0 +immo, 0 immobilien, 0 imperia.it, 0 in, 0 @@ -2504,6 +2589,7 @@ info.az, 0 info.bb, 0 info.co, 0 info.ec, 0 +info.et, 0 info.ht, 0 info.hu, 0 info.ki, 0 @@ -2518,6 +2604,7 @@ info.pr, 0 info.ro, 0 info.sd, 0 info.tn, 0 +info.tr, 0 info.tt, 0 info.tz, 0 info.ve, 0 @@ -2557,11 +2644,12 @@ investments, 0 inzai.chiba.jp, 0 io, 0 ip6.arpa, 0 +ipiranga, 0 iq, 0 ir, 0 iraq.museum, 0 -irc.pl, 0 iris.arpa, 0 +irish, 0 irkutsk.ru, 0 iron.museum, 0 iruma.saitama.jp, 0 @@ -2664,6 +2752,8 @@ isla.pr, 0 isleofman.museum, 0 isshiki.aichi.jp, 0 issmarterthanyou.com, 4 +ist, 0 +istanbul, 0 isteingeek.de, 4 istmein.de, 4 isumi.chiba.jp, 0 @@ -2674,6 +2764,7 @@ itako.ibaraki.jp, 0 itakura.gunma.jp, 0 itami.hyogo.jp, 0 itano.tokushima.jp, 0 +itau, 0 itayanagi.aomori.jp, 0 ito.shizuoka.jp, 0 itoigawa.niigata.jp, 0 @@ -2697,6 +2788,7 @@ iwata.shizuoka.jp, 0 iwate.iwate.jp, 0 iwate.jp, 0 iwatsuki.saitama.jp, 0 +iwc, 0 iwi.nz, 0 iyo.ehime.jp, 0 iz.hr, 0 @@ -2716,6 +2808,7 @@ jamal.ru, 0 jamison.museum, 0 jan-mayen.no, 0 jar.ru, 0 +java, 0 jaworzno.pl, 0 je, 0 jefferson.museum, 0 @@ -2756,6 +2849,7 @@ joyo.kyoto.jp, 0 jp, 0 jp.net, 4 jpn.com, 4 +jprs, 0 js.cn, 0 judaica.museum, 0 judygarland.museum, 0 @@ -2798,7 +2892,6 @@ k12.mo.us, 0 k12.ms.us, 0 k12.mt.us, 0 k12.nc.us, 0 -k12.nd.us, 0 k12.ne.us, 0 k12.nh.us, 0 k12.nj.us, 0 @@ -2813,6 +2906,7 @@ k12.pr.us, 0 k12.ri.us, 0 k12.sc.us, 0 k12.tn.us, 0 +k12.tr, 0 k12.tx.us, 0 k12.ut.us, 0 k12.va.us, 0 @@ -2977,10 +3071,12 @@ kazimierz-dolny.pl, 0 kazo.saitama.jp, 0 kazuno.akita.jp, 0 kchr.ru, 0 +kddi, 0 ke, 2 keisen.fukuoka.jp, 0 kembuchi.hokkaido.jp, 0 kemerovo.ru, 0 +kep.tr, 0 kepno.pl, 0 kesennuma.miyagi.jp, 0 ketrzyn.pl, 0 @@ -3073,6 +3169,7 @@ kochi.jp, 0 kochi.kochi.jp, 0 kodaira.tokyo.jp, 0 koebenhavn.museum, 0 +koeln, 0 koeln.museum, 0 koenig.ru, 0 kofu.yamanashi.jp, 0 @@ -3136,7 +3233,7 @@ kr.it, 0 kr.ua, 0 kraanghke.no, 0 kragero.no, 0 -krakow.pl, 0 +krakow.pl, 4 krasnoyarsk.ru, 0 krd, 0 kred, 0 @@ -3248,7 +3345,9 @@ lardal.no, 0 larsson.museum, 0 larvik.no, 0 laspezia.it, 0 +lat, 0 latina.it, 0 +latrobe, 0 lavagis.no, 0 lavangen.no, 0 law.pro, 0 @@ -3268,7 +3367,9 @@ lebork.pl, 0 lebtimnetz.de, 4 lecce.it, 0 lecco.it, 0 +leclerc, 0 leg.br, 0 +legal, 0 legnica.pl, 0 leikanger.no, 0 leirfjord.no, 0 @@ -3288,6 +3389,7 @@ lg.ua, 0 lgbt, 0 li, 0 li.it, 0 +liaison, 0 lib.ak.us, 0 lib.al.us, 0 lib.ar.us, 0 @@ -3343,6 +3445,7 @@ lib.vt.us, 0 lib.wa.us, 0 lib.wi.us, 0 lib.wy.us, 0 +lidl, 0 lier.no, 0 lierne.no, 0 life, 0 @@ -3394,6 +3497,7 @@ ls, 0 lt, 0 lt.it, 0 lt.ua, 0 +ltd, 0 ltd.co.im, 0 ltd.gi, 0 ltd.lk, 0 @@ -3436,6 +3540,7 @@ magadan.ru, 0 magazine.aero, 0 magnitka.ru, 0 maibara.shiga.jp, 0 +maif, 0 mail.pl, 0 maintenance.aero, 0 maison, 0 @@ -3473,6 +3578,7 @@ market, 0 marketing, 0 marketplace.aero, 0 marnardal.no, 0 +marriott, 0 marugame.kagawa.jp, 0 marumori.miyagi.jp, 0 maryland.museum, 0 @@ -3509,7 +3615,6 @@ mazowsze.pl, 0 mazury.pl, 0 mb.ca, 0 mb.it, 0 -mbone.pl, 0 mc, 0 mc.it, 0 md, 0 @@ -3527,7 +3632,7 @@ med.ht, 0 med.ly, 0 med.om, 0 med.pa, 0 -med.pl, 0 +med.pl, 4 med.pro, 0 med.sa, 0 med.sd, 0 @@ -3553,6 +3658,7 @@ meldal.no, 0 melhus.no, 0 meloy.no, 0 meme, 0 +memorial, 0 memorial.museum, 0 menu, 0 meraker.no, 0 @@ -3640,6 +3746,7 @@ mil.sy, 0 mil.tj, 0 mil.tm, 0 mil.to, 0 +mil.tr, 0 mil.tw, 0 mil.tz, 0 mil.uy, 0 @@ -3770,8 +3877,10 @@ molise.it, 0 moma.museum, 0 mombetsu.hokkaido.jp, 0 monash, 0 +money, 0 money.museum, 0 monmouth.museum, 0 +montblanc, 0 monticello.museum, 0 montreal.museum, 0 monza-brianza.it, 0 @@ -3796,7 +3905,6 @@ moscow.museum, 0 moseushi.hokkaido.jp, 0 mosjoen.no, 0 moskenes.no, 0 -mosreg.ru, 0 moss.no, 0 mosvik.no, 0 motegi.tochigi.jp, 0 @@ -3806,6 +3914,7 @@ motorcycles, 0 motosu.gifu.jp, 0 motoyama.kochi.jp, 0 mov, 0 +movistar, 0 mp, 0 mp.br, 0 mq, 0 @@ -3925,6 +4034,7 @@ namdalseid.no, 0 name, 0 name.az, 0 name.eg, 0 +name.et, 0 name.hr, 0 name.jo, 0 name.mk, 0 @@ -3935,6 +4045,7 @@ name.ng, 0 name.pr, 0 name.qa, 0 name.tj, 0 +name.tr, 0 name.tt, 0 name.vn, 0 namegata.ibaraki.jp, 0 @@ -3993,6 +4104,7 @@ navy, 0 nayoro.hokkaido.jp, 0 nb.ca, 0 nc, 0 +nc.tr, 0 nc.us, 0 nd.us, 0 ne, 0 @@ -4120,6 +4232,7 @@ net.tj, 0 net.tm, 0 net.tn, 0 net.to, 0 +net.tr, 0 net.tt, 0 net.tw, 0 net.ua, 0 @@ -4132,6 +4245,7 @@ net.vi, 0 net.vn, 0 net.vu, 0 net.ws, 0 +netbank, 0 network, 0 neues.museum, 0 neustar, 0 @@ -4143,6 +4257,7 @@ newport.museum, 0 news.hu, 0 newspaper.museum, 0 newyork.museum, 0 +nexus, 0 neyagawa.osaka.jp, 0 nf, 0 nf.ca, 0 @@ -4151,14 +4266,12 @@ ng, 0 ngo, 0 ngo.lk, 0 ngo.ph, 0 -ngo.pl, 0 nh.us, 0 nhk, 0 nhs.uk, 0 ni, 2 nic.in, 0 nic.tj, 0 -nic.tr, 1 nichinan.miyazaki.jp, 0 nichinan.tottori.jp, 0 nid.io, 4 @@ -4224,7 +4337,7 @@ nogi.tochigi.jp, 0 noheji.aomori.jp, 0 nom.ad, 0 nom.ag, 0 -nom.br, 0 +nom.br, 2 nom.co, 0 nom.es, 0 nom.fr, 0 @@ -4264,6 +4377,7 @@ nov.ru, 0 novara.it, 0 novosibirsk.ru, 0 nowaruda.pl, 0 +nowruz, 0 nozawaonsen.nagano.jp, 0 np, 2 nr, 0 @@ -4281,6 +4395,7 @@ nt.edu.au, 0 nt.no, 0 nt.ro, 0 ntr.br, 0 +ntt, 0 nu, 0 nu.ca, 0 nu.it, 0 @@ -4307,6 +4422,7 @@ oarai.ibaraki.jp, 0 obama.fukui.jp, 0 obama.nagasaki.jp, 0 obanazawa.yamagata.jp, 0 +obi, 0 obihiro.hokkaido.jp, 0 obira.hokkaido.jp, 0 obu.aichi.jp, 0 @@ -4423,6 +4539,7 @@ onojo.fukuoka.jp, 0 onomichi.hiroshima.jp, 0 ontario.museum, 0 ookuwa.nagano.jp, 0 +ooo, 0 ooshika.nagano.jp, 0 openair.museum, 0 operaunite.com, 4 @@ -4446,6 +4563,7 @@ or.tz, 0 or.ug, 0 or.us, 0 ora.gunma.jp, 0 +oracle, 0 oregon.museum, 0 oregontrail.museum, 0 orenburg.ru, 0 @@ -4483,6 +4601,7 @@ org.ec, 0 org.ee, 0 org.eg, 0 org.es, 0 +org.et, 0 org.ge, 0 org.gg, 0 org.gh, 0 @@ -4569,6 +4688,7 @@ org.tj, 0 org.tm, 0 org.tn, 0 org.to, 0 +org.tr, 0 org.tt, 0 org.tw, 0 org.ua, 0 @@ -4592,6 +4712,7 @@ orsta.no, 0 oryol.ru, 0 os.hedmark.no, 0 os.hordaland.no, 0 +osaka, 0 osaka.jp, 0 osakasayama.osaka.jp, 0 osaki.miyagi.jp, 0 @@ -4677,9 +4798,11 @@ paris.museum, 0 parliament.nz, 0 parma.it, 0 paroch.k12.ma.us, 0 +pars, 0 parti.se, 0 partners, 0 parts, 0 +party, 0 pasadena.museum, 0 passenger-association.aero, 0 pavia.it, 0 @@ -4709,6 +4832,7 @@ pg.it, 0 ph, 0 pharmacien.fr, 0 pharmaciens.km, 0 +pharmacy, 0 pharmacy.museum, 0 philadelphia.museum, 0 philadelphiaarea.museum, 0 @@ -4721,7 +4845,9 @@ photos, 0 physio, 0 pi.it, 0 piacenza.it, 0 +piaget, 0 pics, 0 +pictet, 0 pictures, 0 piedmont.it, 0 piemonte.it, 0 @@ -4734,6 +4860,7 @@ pisa.it, 0 pistoia.it, 0 pisz.pl, 0 pittsburgh.museum, 0 +pizza, 0 pk, 0 pl, 0 pl.ua, 0 @@ -4757,14 +4884,18 @@ podhale.pl, 0 podlasie.pl, 0 podzone.net, 4 podzone.org, 4 +pohl, 0 +poker, 0 pol.dz, 0 pol.ht, 0 +pol.tr, 0 police.uk, 0 polkowice.pl, 0 poltava.ua, 0 pomorskie.pl, 0 pomorze.pl, 0 pordenone.it, 0 +porn, 0 porsanger.no, 0 porsangu.no, 0 porsgrunn.no, 0 @@ -4776,7 +4907,7 @@ post, 0 posts-and-telecommunications.museum, 0 potenza.it, 0 powiat.pl, 0 -poznan.pl, 0 +poznan.pl, 4 pp.az, 0 pp.ru, 0 pp.se, 0 @@ -4823,6 +4954,7 @@ prochowice.pl, 0 prod, 0 production.aero, 0 productions, 0 +prof, 0 prof.pr, 0 project.museum, 0 properties, 0 @@ -4902,6 +5034,7 @@ recipes, 0 recreation.aero, 0 red, 0 red.sv, 0 +redstone, 0 reggio-calabria.it, 0 reggio-emilia.it, 0 reggiocalabria.it, 0 @@ -4909,6 +5042,7 @@ reggioemilia.it, 0 rehab, 0 reise, 0 reisen, 0 +reit, 0 reklam.hu, 0 rel.ht, 0 rel.pl, 0 @@ -4928,6 +5062,7 @@ research.aero, 0 research.museum, 0 resistance.museum, 0 rest, 0 +restaurant, 0 reviews, 0 rg.it, 0 rhcloud.com, 4 @@ -4946,6 +5081,7 @@ ringerike.no, 0 ringsaker.no, 0 rio, 0 riodejaneiro.museum, 0 +rip, 0 rishiri.hokkaido.jp, 0 rishirifuji.hokkaido.jp, 0 risor.no, 0 @@ -5069,6 +5205,7 @@ sakurai.nara.jp, 0 sakyo.kyoto.jp, 0 salangen.no, 0 salat.no, 0 +sale, 0 salem.museum, 0 salerno.it, 0 saltdal.no, 0 @@ -5095,6 +5232,7 @@ sanjo.niigata.jp, 0 sannan.hyogo.jp, 0 sannohe.aomori.jp, 0 sano.tochigi.jp, 0 +sanofi, 0 sanok.pl, 0 santabarbara.museum, 0 santacruz.museum, 0 @@ -5107,6 +5245,7 @@ sar.it, 0 saratov.ru, 0 sardegna.it, 0 sardinia.it, 0 +sarl, 0 saroma.hokkaido.jp, 0 sarpsborg.no, 0 sarufutsu.hokkaido.jp, 0 @@ -5124,6 +5263,7 @@ sauherad.no, 0 savannahga.museum, 0 saves-the-whales.com, 4 savona.it, 0 +saxo, 0 sayama.osaka.jp, 0 sayama.saitama.jp, 0 sayo.hyogo.jp, 0 @@ -5156,8 +5296,10 @@ school.museum, 0 school.na, 0 school.nz, 0 schule, 0 +schwarz, 0 schweiz.museum, 0 sci.eg, 0 +science, 0 science-fiction.museum, 0 science.museum, 0 scienceandhistory.museum, 0 @@ -5168,6 +5310,7 @@ sciencehistory.museum, 0 sciences.museum, 0 sciencesnaturelles.museum, 0 scientist.aero, 0 +scor, 0 scot, 0 scotland.museum, 0 scrapper-site.net, 4 @@ -5207,6 +5350,7 @@ sellsyourhome.org, 4 semboku.akita.jp, 0 semine.miyagi.jp, 0 sendai.jp, 2 +sener, 0 sennan.osaka.jp, 0 seoul.kr, 0 sera.hiroshima.jp, 0 @@ -5217,6 +5361,7 @@ servebbs.org, 4 serveftp.net, 4 serveftp.org, 4 servegame.org, 4 +service.gov.uk, 4 services, 0 services.aero, 0 setagaya.tokyo.jp, 0 @@ -5226,6 +5371,7 @@ settlement.museum, 0 settlers.museum, 0 settsu.osaka.jp, 0 sevastopol.ua, 0 +sew, 0 sex.hu, 0 sex.pl, 0 sexy, 0 @@ -5239,6 +5385,7 @@ shari.hokkaido.jp, 0 sharp, 0 shell.museum, 0 sherbrooke.museum, 0 +shia, 0 shibata.miyagi.jp, 0 shibata.niigata.jp, 0 shibecha.hokkaido.jp, 0 @@ -5343,7 +5490,6 @@ sibenik.museum, 0 sic.it, 0 sicilia.it, 0 sicily.it, 0 -siedlce.pl, 0 siellak.no, 0 siena.it, 0 sigdal.no, 0 @@ -5373,6 +5519,7 @@ sklep.pl, 0 skoczow.pl, 0 skodje.no, 0 skole.museum, 0 +sky, 0 skydiving.aero, 0 sl, 0 slask.pl, 0 @@ -5421,7 +5568,7 @@ sondrio.it, 0 songdalen.no, 0 soni.nara.jp, 0 soo.kagoshima.jp, 0 -sopot.pl, 0 +sopot.pl, 4 sor-aurdal.no, 0 sor-fron.no, 0 sor-odal.no, 0 @@ -5472,6 +5619,8 @@ station.museum, 0 stavanger.no, 0 stavern.no, 0 stavropol.ru, 0 +stc, 0 +stcgroup, 0 steam.museum, 0 steiermark.museum, 0 steigen.no, 0 @@ -5523,6 +5672,7 @@ sunndal.no, 0 supplies, 0 supply, 0 support, 0 +surf, 0 surgeonshall.museum, 0 surgery, 0 surgut.ru, 0 @@ -5546,9 +5696,11 @@ sweden.museum, 0 swidnica.pl, 0 swiebodzin.pl, 0 swinoujscie.pl, 0 +swiss, 0 sx, 0 sx.cn, 0 sy, 0 +sydney, 0 sydney.museum, 0 sykkylven.no, 0 systems, 0 @@ -5577,6 +5729,7 @@ taiji.wakayama.jp, 0 taiki.hokkaido.jp, 0 taiki.mie.jp, 0 tainai.niigata.jp, 0 +taipei, 0 taira.toyama.jp, 0 taishi.hyogo.jp, 0 taishi.osaka.jp, 0 @@ -5663,6 +5816,7 @@ tax, 0 taxi.aero, 0 taxi.br, 0 tc, 0 +tci, 0 tcm.museum, 0 td, 0 te.it, 0 @@ -5672,9 +5826,12 @@ tec.ve, 0 technology, 0 technology.museum, 0 tel, 0 +tel.tr, 0 teledata.mz, 1 +telefonica, 0 telekommunikation.museum, 0 television.museum, 0 +temasek, 0 tempio-olbia.it, 0 tempioolbia.it, 0 tendo.yamagata.jp, 0 @@ -5826,7 +5983,7 @@ tozawa.yamagata.jp, 0 tozsde.hu, 0 tp, 0 tp.it, 0 -tr, 2 +tr, 0 tr.it, 0 tr.no, 0 tra.kp, 0 @@ -5880,6 +6037,7 @@ trolley.museum, 0 tromsa.no, 0 tromso.no, 0 trondheim.no, 0 +trust, 0 trust.museum, 0 trustee.museum, 0 trysil.no, 0 @@ -5915,6 +6073,7 @@ tsuwano.shimane.jp, 0 tsuyama.okayama.jp, 0 tt, 0 tt.im, 0 +tui, 0 tula.ru, 0 tur.ar, 0 tur.br, 0 @@ -5932,6 +6091,7 @@ tv.im, 0 tv.it, 0 tv.na, 0 tv.sd, 0 +tv.tr, 0 tv.tz, 0 tvedestrand.no, 0 tver.ru, 0 @@ -6028,7 +6188,6 @@ usarts.museum, 0 uscountryestate.museum, 0 usculture.museum, 0 usdecorativearts.museum, 0 -usenet.pl, 0 usgarden.museum, 0 ushiku.ibaraki.jp, 0 ushistory.museum, 0 @@ -6136,6 +6295,7 @@ vic.au, 0 vic.edu.au, 0 vic.gov.au, 0 vicenza.it, 0 +video, 0 video.hu, 0 vik.no, 0 viking.museum, 0 @@ -6145,10 +6305,13 @@ villas, 0 vindafjord.no, 0 vinnica.ua, 0 vinnytsia.ua, 0 +virgin, 0 virginia.museum, 0 virtual.museum, 0 virtuel.museum, 0 vision, 0 +vista, 0 +vistaprint, 0 viterbo.it, 0 vlaanderen, 0 vlaanderen.museum, 0 @@ -6222,6 +6385,7 @@ web.lk, 0 web.nf, 0 web.pk, 0 web.tj, 0 +web.tr, 0 web.ve, 0 webcam, 0 webhop.biz, 4 @@ -6257,9 +6421,10 @@ workinggroup.aero, 0 works, 0 works.aero, 0 workshop.museum, 0 +world, 0 worse-than.tv, 4 writesthisblog.com, 4 -wroc.pl, 0 +wroc.pl, 4 wroclaw.pl, 0 ws, 0 ws.na, 0 @@ -6271,29 +6436,49 @@ www.ro, 0 wy.us, 0 x.bg, 0 x.se, 0 +xerox, 0 xj.cn, 0 +xn--0trq7p7nn.jp, 0 +xn--1ctwo.jp, 0 +xn--1lqs03n.jp, 0 +xn--1lqs71d.jp, 0 xn--1qqw23a, 0 +xn--2m4a15e.jp, 0 +xn--30rr7y, 0 +xn--32vp30h.jp, 0 xn--3bst00m, 0 xn--3ds443g, 0 xn--3e0b707e, 0 xn--45brj9c, 0 xn--45q11c, 0 xn--4gbrim, 0 +xn--4it168d.jp, 0 +xn--4it797k.jp, 0 +xn--4pvxs.jp, 0 xn--54b7fta0cc, 0 xn--55qw42g, 0 xn--55qx5d, 0 xn--55qx5d.cn, 0 xn--55qx5d.hk, 0 +xn--5js045d.jp, 0 +xn--5rtp49c.jp, 0 +xn--5rtq34k.jp, 0 +xn--6btw5a.jp, 0 xn--6frz82g, 0 +xn--6orx2r.jp, 0 xn--6qq986b3xl, 0 +xn--7t0a264c.jp, 0 xn--80adxhks, 0 xn--80ao21a, 0 xn--80asehdb, 0 xn--80aswg, 0 xn--80au.xn--90a3ac, 0 +xn--8ltr62k.jp, 0 +xn--8pvr4u.jp, 0 xn--90a3ac, 0 xn--90azh.xn--90a3ac, 0 xn--9dbhblg6di.museum, 0 +xn--9et52u, 0 xn--andy-ira.no, 0 xn--aroport-bya.ci, 0 xn--asky-ira.no, 0 @@ -6301,6 +6486,7 @@ xn--aurskog-hland-jnb.no, 0 xn--avery-yua.no, 0 xn--b-5ga.nordland.no, 0 xn--b-5ga.telemark.no, 0 +xn--b4w605ferd, 0 xn--bdddj-mrabd.no, 0 xn--bearalvhki-y4a.no, 0 xn--berlevg-jxa.no, 0 @@ -6319,6 +6505,7 @@ xn--brum-voa.no, 0 xn--btsfjord-9za.no, 0 xn--c1avg, 0 xn--c1avg.xn--90a3ac, 0 +xn--c3s14m.jp, 0 xn--cg4bki, 0 xn--ciqpn.hk, 0 xn--clchc0ea0b2g2a9gcd, 0 @@ -6330,11 +6517,19 @@ xn--czru2d, 0 xn--czrw28b.tw, 0 xn--d1acj3b, 0 xn--d1at.xn--90a3ac, 0 +xn--d5qv7z876c.jp, 0 xn--davvenjrga-y4a.no, 0 +xn--djrs72d6uy.jp, 0 +xn--djty4k.jp, 0 xn--dnna-gra.no, 0 xn--drbak-wua.no, 0 xn--dyry-ira.no, 0 +xn--efvn9s.jp, 0 +xn--efvy88h, 0 +xn--ehqz56n.jp, 0 +xn--elqq16h.jp, 0 xn--eveni-0qa01ga.no, 0 +xn--f6qx53a.jp, 0 xn--finny-yua.no, 0 xn--fiq228c5hs, 0 xn--fiq64b, 0 @@ -6344,6 +6539,7 @@ xn--fjord-lra.no, 0 xn--fjq720a, 0 xn--fl-zia.no, 0 xn--flor-jra.no, 0 +xn--flw351e, 0 xn--fpcrj9c3d, 0 xn--frde-gra.no, 0 xn--frna-woa.no, 0 @@ -6382,9 +6578,15 @@ xn--j1amh, 0 xn--j6w193g, 0 xn--jlster-bya.no, 0 xn--jrpeland-54a.no, 0 +xn--k7yn95e.jp, 0 xn--karmy-yua.no, 0 +xn--kbrq7o.jp, 0 xn--kfjord-iua.no, 0 xn--klbu-woa.no, 0 +xn--klt787d.jp, 0 +xn--kltp7d.jp, 0 +xn--kltx9a.jp, 0 +xn--klty5x.jp, 0 xn--koluokta-7ya57h.no, 0 xn--kprw13d, 0 xn--kpry57d, 0 @@ -6434,10 +6636,12 @@ xn--mgberp4a5d4a87g, 0 xn--mgberp4a5d4ar, 0 xn--mgbqly7c0a67fbc, 0 xn--mgbqly7cvafr, 0 +xn--mgbt3dhd, 0 xn--mgbtf8fl, 0 xn--mgbx4cd0ab, 0 xn--mjndalen-64a.no, 0 xn--mk0axi.hk, 0 +xn--mkru45i.jp, 0 xn--mlatvuopmi-s4a.no, 0 xn--mli-tla.no, 0 xn--mlselv-iua.no, 0 @@ -6451,12 +6655,15 @@ xn--muost-0qa.no, 0 xn--mxtq1m, 0 xn--mxtq1m.hk, 0 xn--ngbc5azd, 0 +xn--nit225k.jp, 0 xn--nmesjevuemie-tcba.no, 0 xn--nnx388a, 0 xn--node, 0 xn--nqv7f, 0 xn--nqv7fs00ema, 0 xn--nry-yla5g.no, 0 +xn--ntso0iqx3a.jp, 0 +xn--ntsq17g.jp, 0 xn--nttery-byae.no, 0 xn--nvuotna-hwa.no, 0 xn--o1ac.xn--90a3ac, 0 @@ -6473,7 +6680,10 @@ xn--p1acf, 0 xn--p1ai, 0 xn--pgbs0dh, 0 xn--porsgu-sta26f.no, 0 +xn--pssu33l.jp, 0 xn--q9jyb4c, 0 +xn--qcka1pmc, 0 +xn--qqqt11m.jp, 0 xn--rady-ira.no, 0 xn--rdal-poa.no, 0 xn--rde-ula.no, 0 @@ -6482,11 +6692,15 @@ xn--rennesy-v1a.no, 0 xn--rhkkervju-01af.no, 0 xn--rholt-mra.no, 0 xn--rhqv96g, 0 +xn--rht27z.jp, 0 +xn--rht3d.jp, 0 +xn--rht61e.jp, 0 xn--risa-5na.no, 0 xn--risr-ira.no, 0 xn--rland-uua.no, 0 xn--rlingen-mxa.no, 0 xn--rmskog-bya.no, 0 +xn--rny31h.jp, 0 xn--rros-gra.no, 0 xn--rskog-uua.no, 0 xn--rst-0na.no, 0 @@ -6526,6 +6740,7 @@ xn--stre-toten-zcb.no, 0 xn--tjme-hra.no, 0 xn--tn0ag.hk, 0 xn--tnsberg-q1a.no, 0 +xn--tor131o.jp, 0 xn--trany-yua.no, 0 xn--trgstad-r1a.no, 0 xn--trna-woa.no, 0 @@ -6534,21 +6749,28 @@ xn--tysvr-vra.no, 0 xn--uc0atv.hk, 0 xn--uc0atv.tw, 0 xn--uc0ay4a.hk, 0 +xn--uist22h.jp, 0 +xn--uisz3g.jp, 0 xn--unjrga-rta.no, 0 xn--unup4y, 0 +xn--uuwu58a.jp, 0 xn--vads-jra.no, 0 xn--vard-jra.no, 0 xn--vegrshei-c0a.no, 0 +xn--vermgensberater-ctb, 0 +xn--vermgensberatung-pwb, 0 xn--vestvgy-ixa6o.no, 0 xn--vg-yiab.no, 0 xn--vgan-qoa.no, 0 xn--vgsy-qoa0j.no, 0 +xn--vgu402c.jp, 0 xn--vhquv, 0 xn--vler-qoa.hedmark.no, 0 xn--vler-qoa.xn--stfold-9xa.no, 0 xn--vre-eiker-k8a.no, 0 xn--vrggt-xqad.no, 0 xn--vry-yla5g.no, 0 +xn--vuq861b, 0 xn--wcvs22d.hk, 0 xn--wgbh1c, 0 xn--wgbl6a, 0 @@ -6560,6 +6782,7 @@ xn--yfro4i67o, 0 xn--ygarden-p1a.no, 0 xn--ygbi2ammx, 0 xn--ystre-slidre-ujb.no, 0 +xn--zbx025d.jp, 0 xn--zf0ao64a.tw, 0 xn--zf0avx.hk, 0 xn--zfr164b, 0 @@ -6648,6 +6871,7 @@ yokoshibahikari.chiba.jp, 0 yokosuka.kanagawa.jp, 0 yokote.akita.jp, 0 yokoze.saitama.jp, 0 +yolasite.com, 4 yomitan.okinawa.jp, 0 yonabaru.okinawa.jp, 0 yonago.tottori.jp, 0 @@ -6695,7 +6919,7 @@ za.net, 4 za.org, 4 zachpomor.pl, 0 zagan.pl, 0 -zakopane.pl, 0 +zakopane.pl, 4 zama.kanagawa.jp, 0 zamami.okinawa.jp, 0 zao.miyagi.jp, 0 diff --git a/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc b/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc index 7a4a5283a81..22bd963ad4b 100644 --- a/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc +++ b/chromium/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc @@ -82,7 +82,7 @@ class RegistryControlledDomainTest : public testing::Test { SetFindDomainGraph(graph, sizeof(Graph)); } - virtual void TearDown() { SetFindDomainGraph(); } + void TearDown() override { SetFindDomainGraph(); } }; TEST_F(RegistryControlledDomainTest, TestGetDomainAndRegistry) { diff --git a/chromium/net/base/request_priority.h b/chromium/net/base/request_priority.h index e663610fff4..dcf77936423 100644 --- a/chromium/net/base/request_priority.h +++ b/chromium/net/base/request_priority.h @@ -11,6 +11,10 @@ namespace net { // Prioritization used in various parts of the networking code such // as connection prioritization and resource loading prioritization. +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net +// GENERATED_JAVA_CLASS_NAME_OVERRIDE: RequestPriority +// GENERATED_JAVA_PREFIX_TO_STRIP: enum RequestPriority { IDLE = 0, MINIMUM_PRIORITY = IDLE, diff --git a/chromium/net/base/sdch_dictionary_fetcher.cc b/chromium/net/base/sdch_dictionary_fetcher.cc deleted file mode 100644 index aa2061eba8e..00000000000 --- a/chromium/net/base/sdch_dictionary_fetcher.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2014 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 "net/base/sdch_dictionary_fetcher.h" - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/message_loop/message_loop.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_status.h" - -namespace net { - -SdchDictionaryFetcher::SdchDictionaryFetcher( - SdchManager* manager, - URLRequestContextGetter* context) - : manager_(manager), - weak_factory_(this), - task_is_pending_(false), - context_(context) { - DCHECK(CalledOnValidThread()); - DCHECK(manager); -} - -SdchDictionaryFetcher::~SdchDictionaryFetcher() { - DCHECK(CalledOnValidThread()); -} - -void SdchDictionaryFetcher::Schedule(const GURL& dictionary_url) { - DCHECK(CalledOnValidThread()); - - // Avoid pushing duplicate copy onto queue. We may fetch this url again later - // and get a different dictionary, but there is no reason to have it in the - // queue twice at one time. - if (!fetch_queue_.empty() && fetch_queue_.back() == dictionary_url) { - SdchManager::SdchErrorRecovery( - SdchManager::DICTIONARY_ALREADY_SCHEDULED_TO_DOWNLOAD); - return; - } - if (attempted_load_.find(dictionary_url) != attempted_load_.end()) { - SdchManager::SdchErrorRecovery( - SdchManager::DICTIONARY_ALREADY_TRIED_TO_DOWNLOAD); - return; - } - attempted_load_.insert(dictionary_url); - fetch_queue_.push(dictionary_url); - ScheduleDelayedRun(); -} - -void SdchDictionaryFetcher::Cancel() { - DCHECK(CalledOnValidThread()); - - while (!fetch_queue_.empty()) - fetch_queue_.pop(); - attempted_load_.clear(); - weak_factory_.InvalidateWeakPtrs(); - current_fetch_.reset(NULL); -} - -void SdchDictionaryFetcher::ScheduleDelayedRun() { - if (fetch_queue_.empty() || current_fetch_.get() || task_is_pending_) - return; - base::MessageLoop::current()->PostDelayedTask(FROM_HERE, - base::Bind(&SdchDictionaryFetcher::StartFetching, - weak_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kMsDelayFromRequestTillDownload)); - task_is_pending_ = true; -} - -void SdchDictionaryFetcher::StartFetching() { - DCHECK(CalledOnValidThread()); - DCHECK(task_is_pending_); - task_is_pending_ = false; - - // Handle losing the race against Cancel(). - if (fetch_queue_.empty()) - return; - - DCHECK(context_.get()); - current_fetch_.reset(URLFetcher::Create( - fetch_queue_.front(), URLFetcher::GET, this)); - fetch_queue_.pop(); - current_fetch_->SetRequestContext(context_.get()); - current_fetch_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | - LOAD_DO_NOT_SAVE_COOKIES); - current_fetch_->Start(); -} - -void SdchDictionaryFetcher::OnURLFetchComplete( - const URLFetcher* source) { - DCHECK(CalledOnValidThread()); - if ((200 == source->GetResponseCode()) && - (source->GetStatus().status() == URLRequestStatus::SUCCESS)) { - std::string data; - source->GetResponseAsString(&data); - manager_->AddSdchDictionary(data, source->GetURL()); - } - current_fetch_.reset(NULL); - ScheduleDelayedRun(); -} - -} // namespace net diff --git a/chromium/net/base/sdch_dictionary_fetcher.h b/chromium/net/base/sdch_dictionary_fetcher.h deleted file mode 100644 index b657b8f80c3..00000000000 --- a/chromium/net/base/sdch_dictionary_fetcher.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 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. - -// Support modularity by calling to load a new SDCH filter dictionary. -// Note that this sort of calling can't be done in the /net directory, as it has -// no concept of the HTTP cache (which is only visible at the browser level). - -#ifndef NET_BASE_SDCH_DICTIONARY_FETCHER_H_ -#define NET_BASE_SDCH_DICTIONARY_FETCHER_H_ - -#include <queue> -#include <set> -#include <string> - -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "net/base/sdch_manager.h" -#include "net/url_request/url_fetcher_delegate.h" - -namespace net { - -class URLFetcher; -class URLRequestContextGetter; - -class NET_EXPORT SdchDictionaryFetcher - : public URLFetcherDelegate, - public SdchFetcher, - public base::NonThreadSafe { - public: - // Consumer must guarantee that the SdchManager pointer outlives - // this object. The current implementation guarantees this by - // the SdchManager owning this object. - SdchDictionaryFetcher(SdchManager* manager, - URLRequestContextGetter* context); - virtual ~SdchDictionaryFetcher(); - - // Implementation of SdchFetcher class. - virtual void Schedule(const GURL& dictionary_url) OVERRIDE; - virtual void Cancel() OVERRIDE; - - private: - // Delay in ms between Schedule and actual download. - // This leaves the URL in a queue, which is de-duped, so that there is less - // chance we'll try to load the same URL multiple times when a pile of - // page subresources (or tabs opened in parallel) all suggest the dictionary. - static const int kMsDelayFromRequestTillDownload = 100; - - // Ensure the download after the above delay. - void ScheduleDelayedRun(); - - // Make sure we're processing (or waiting for) the the arrival of the next URL - // in the |fetch_queue_|. - void StartFetching(); - - // Implementation of URLFetcherDelegate. Called after transmission - // completes (either successfully or with failure). - virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE; - - SdchManager* const manager_; - - // A queue of URLs that are being used to download dictionaries. - std::queue<GURL> fetch_queue_; - // The currently outstanding URL fetch of a dicitonary. - // If this is null, then there is no outstanding request. - scoped_ptr<URLFetcher> current_fetch_; - - // Always spread out the dictionary fetches, so that they don't steal - // bandwidth from the actual page load. Create delayed tasks to spread out - // the download. - base::WeakPtrFactory<SdchDictionaryFetcher> weak_factory_; - bool task_is_pending_; - - // Althought the SDCH spec does not preclude a server from using a single URL - // to load several distinct dictionaries (by telling a client to load a - // dictionary from an URL several times), current implementations seem to have - // that 1-1 relationship (i.e., each URL points at a single dictionary, and - // the dictionary content does not change over time, and hence is not worth - // trying to load more than once). In addition, some dictionaries prove - // unloadable only after downloading them (because they are too large? ...or - // malformed?). As a protective element, Chromium will *only* load a - // dictionary at most once from a given URL (so that it doesn't waste - // bandwidth trying repeatedly). - // The following set lists all the dictionary URLs that we've tried to load, - // so that we won't try to load from an URL more than once. - // TODO(jar): Try to augment the SDCH proposal to include this restiction. - std::set<GURL> attempted_load_; - - // Store the system_url_request_context_getter to use it when we start - // fetching. - scoped_refptr<URLRequestContextGetter> context_; - - DISALLOW_COPY_AND_ASSIGN(SdchDictionaryFetcher); -}; - -} // namespace net - -#endif // NET_BASE_SDCH_DICTIONARY_FETCHER_H_ diff --git a/chromium/net/base/sdch_manager.cc b/chromium/net/base/sdch_manager.cc index 8892c13a7c4..1285ad9383a 100644 --- a/chromium/net/base/sdch_manager.cc +++ b/chromium/net/base/sdch_manager.cc @@ -11,8 +11,30 @@ #include "base/strings/string_util.h" #include "crypto/sha2.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "net/base/sdch_observer.h" #include "net/url_request/url_request_http_job.h" +namespace { + +void StripTrailingDot(GURL* gurl) { + std::string host(gurl->host()); + + if (host.empty()) + return; + + if (*host.rbegin() != '.') + return; + + host.resize(host.size() - 1); + + GURL::Replacements replacements; + replacements.SetHostStr(host); + *gurl = gurl->ReplaceComponents(replacements); + return; +} + +} // namespace + namespace net { //------------------------------------------------------------------------------ @@ -22,7 +44,7 @@ namespace net { #if defined(OS_ANDROID) || defined(OS_IOS) // static const size_t SdchManager::kMaxDictionaryCount = 1; -const size_t SdchManager::kMaxDictionarySize = 150 * 1000; +const size_t SdchManager::kMaxDictionarySize = 500 * 1000; #else // static const size_t SdchManager::kMaxDictionaryCount = 20; @@ -33,7 +55,7 @@ const size_t SdchManager::kMaxDictionarySize = 1000 * 1000; bool SdchManager::g_sdch_enabled_ = true; // static -bool SdchManager::g_secure_scheme_supported_ = false; +bool SdchManager::g_secure_scheme_supported_ = true; //------------------------------------------------------------------------------ SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, @@ -69,7 +91,8 @@ bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) { 3. The request URI path-matches the path header of the dictionary. 4. The request is not an HTTPS request. We can override (ignore) item (4) only when we have explicitly enabled - HTTPS support AND dictionary has been acquired over HTTPS. + HTTPS support AND the dictionary acquisition scheme matches the target + url scheme. */ if (!DomainMatch(target_url, domain_)) return false; @@ -79,7 +102,7 @@ bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) { return false; if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) return false; - if (target_url.SchemeIsSecure() && !url_.SchemeIsSecure()) + if (target_url.SchemeIsSecure() != url_.SchemeIsSecure()) return false; if (base::Time::Now() > expiration_) return false; @@ -158,8 +181,9 @@ bool SdchManager::Dictionary::CanUse(const GURL& referring_url) { 3. The request URL path-matches the path attribute of the dictionary. 4. The request is not an HTTPS request. We can override (ignore) item (4) only when we have explicitly enabled - HTTPS support AND dictionary has been acquired over HTTPS. -*/ + HTTPS support AND the dictionary acquisition scheme matches the target + url scheme. + */ if (!DomainMatch(referring_url, domain_)) { SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_DOMAIN); return false; @@ -178,7 +202,7 @@ bool SdchManager::Dictionary::CanUse(const GURL& referring_url) { SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME); return false; } - if (referring_url.SchemeIsSecure() && !url_.SchemeIsSecure()) { + if (referring_url.SchemeIsSecure() != url_.SchemeIsSecure()) { SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME); return false; } @@ -219,11 +243,11 @@ bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, //------------------------------------------------------------------------------ SdchManager::SdchManager() { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); } SdchManager::~SdchManager() { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); while (!dictionaries_.empty()) { DictionaryMap::iterator it = dictionaries_.begin(); dictionaries_.erase(it->first); @@ -232,16 +256,15 @@ SdchManager::~SdchManager() { void SdchManager::ClearData() { blacklisted_domains_.clear(); - exponential_blacklist_count_.clear(); allow_latency_experiment_.clear(); - if (fetcher_.get()) - fetcher_->Cancel(); // Note that this may result in not having dictionaries we've advertised // for incoming responses. The window is relatively small (as ClearData() // is not expected to be called frequently), so we rely on meta-refresh // to handle this case. dictionaries_.clear(); + + FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this)); } // static @@ -249,11 +272,6 @@ void SdchManager::SdchErrorRecovery(ProblemCodes problem) { UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE); } -void SdchManager::set_sdch_fetcher(SdchFetcher* fetcher) { - DCHECK(CalledOnValidThread()); - fetcher_.reset(fetcher); -} - // static void SdchManager::EnableSdchSupport(bool enabled) { g_sdch_enabled_ = enabled; @@ -264,55 +282,67 @@ void SdchManager::EnableSecureSchemeSupport(bool enabled) { g_secure_scheme_supported_ = enabled; } -void SdchManager::BlacklistDomain(const GURL& url) { +void SdchManager::BlacklistDomain(const GURL& url, + ProblemCodes blacklist_reason) { SetAllowLatencyExperiment(url, false); - std::string domain(StringToLowerASCII(url.host())); - int count = blacklisted_domains_[domain]; - if (count > 0) + BlacklistInfo* blacklist_info = + &blacklisted_domains_[base::StringToLowerASCII(url.host())]; + + if (blacklist_info->count > 0) return; // Domain is already blacklisted. - count = 1 + 2 * exponential_blacklist_count_[domain]; - if (count > 0) - exponential_blacklist_count_[domain] = count; - else - count = INT_MAX; + if (blacklist_info->exponential_count > (INT_MAX - 1) / 2) { + blacklist_info->exponential_count = INT_MAX; + } else { + blacklist_info->exponential_count = + blacklist_info->exponential_count * 2 + 1; + } - blacklisted_domains_[domain] = count; + blacklist_info->count = blacklist_info->exponential_count; + blacklist_info->reason = blacklist_reason; } -void SdchManager::BlacklistDomainForever(const GURL& url) { +void SdchManager::BlacklistDomainForever(const GURL& url, + ProblemCodes blacklist_reason) { SetAllowLatencyExperiment(url, false); - std::string domain(StringToLowerASCII(url.host())); - exponential_blacklist_count_[domain] = INT_MAX; - blacklisted_domains_[domain] = INT_MAX; + BlacklistInfo* blacklist_info = + &blacklisted_domains_[base::StringToLowerASCII(url.host())]; + blacklist_info->count = INT_MAX; + blacklist_info->exponential_count = INT_MAX; + blacklist_info->reason = blacklist_reason; } void SdchManager::ClearBlacklistings() { blacklisted_domains_.clear(); - exponential_blacklist_count_.clear(); } void SdchManager::ClearDomainBlacklisting(const std::string& domain) { - blacklisted_domains_.erase(StringToLowerASCII(domain)); + BlacklistInfo* blacklist_info = &blacklisted_domains_[ + base::StringToLowerASCII(domain)]; + blacklist_info->count = 0; + blacklist_info->reason = MIN_PROBLEM_CODE; } int SdchManager::BlackListDomainCount(const std::string& domain) { - if (blacklisted_domains_.end() == blacklisted_domains_.find(domain)) + std::string domain_lower(base::StringToLowerASCII(domain)); + + if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) return 0; - return blacklisted_domains_[StringToLowerASCII(domain)]; + return blacklisted_domains_[domain_lower].count; } int SdchManager::BlacklistDomainExponential(const std::string& domain) { - if (exponential_blacklist_count_.end() == - exponential_blacklist_count_.find(domain)) + std::string domain_lower(base::StringToLowerASCII(domain)); + + if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) return 0; - return exponential_blacklist_count_[StringToLowerASCII(domain)]; + return blacklisted_domains_[domain_lower].exponential_count; } bool SdchManager::IsInSupportedDomain(const GURL& url) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (!g_sdch_enabled_ ) return false; @@ -322,30 +352,39 @@ bool SdchManager::IsInSupportedDomain(const GURL& url) { if (blacklisted_domains_.empty()) return true; - std::string domain(StringToLowerASCII(url.host())); - DomainCounter::iterator it = blacklisted_domains_.find(domain); - if (blacklisted_domains_.end() == it) + DomainBlacklistInfo::iterator it = + blacklisted_domains_.find(base::StringToLowerASCII(url.host())); + if (blacklisted_domains_.end() == it || it->second.count == 0) return true; - int count = it->second - 1; - if (count > 0) - blacklisted_domains_[domain] = count; - else - blacklisted_domains_.erase(domain); + UMA_HISTOGRAM_ENUMERATION("Sdch3.BlacklistReason", it->second.reason, + MAX_PROBLEM_CODE); SdchErrorRecovery(DOMAIN_BLACKLIST_INCLUDES_TARGET); + + int count = it->second.count - 1; + if (count > 0) { + it->second.count = count; + } else { + it->second.count = 0; + it->second.reason = MIN_PROBLEM_CODE; + } + return false; } -void SdchManager::FetchDictionary(const GURL& request_url, +void SdchManager::OnGetDictionary(const GURL& request_url, const GURL& dictionary_url) { - DCHECK(CalledOnValidThread()); - if (CanFetchDictionary(request_url, dictionary_url) && fetcher_.get()) - fetcher_->Schedule(dictionary_url); + if (!CanFetchDictionary(request_url, dictionary_url)) + return; + + FOR_EACH_OBSERVER(SdchObserver, + observers_, + OnGetDictionary(this, request_url, dictionary_url)); } bool SdchManager::CanFetchDictionary(const GURL& referring_url, const GURL& dictionary_url) const { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); /* The user agent may retrieve a dictionary from the dictionary URL if all of the following are true: 1 The dictionary URL host name matches the referrer URL host name and @@ -354,7 +393,6 @@ bool SdchManager::CanFetchDictionary(const GURL& referring_url, referrer URL host name 3 The parent domain of the referrer URL host name is not a top level domain - 4 The dictionary URL is not an HTTPS URL. */ // Item (1) above implies item (2). Spec should be updated. // I take "host name match" to be "is identical to" @@ -378,15 +416,101 @@ bool SdchManager::CanFetchDictionary(const GURL& referring_url, return true; } -bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, +void SdchManager::GetVcdiffDictionary( + const std::string& server_hash, + const GURL& referring_url, + scoped_refptr<Dictionary>* dictionary) { + DCHECK(thread_checker_.CalledOnValidThread()); + *dictionary = NULL; + DictionaryMap::iterator it = dictionaries_.find(server_hash); + if (it == dictionaries_.end()) { + return; + } + scoped_refptr<Dictionary> matching_dictionary = it->second; + if (!IsInSupportedDomain(referring_url)) + return; + if (!matching_dictionary->CanUse(referring_url)) + return; + *dictionary = matching_dictionary; +} + +// TODO(jar): If we have evictions from the dictionaries_, then we need to +// change this interface to return a list of reference counted Dictionary +// instances that can be used if/when a server specifies one. +void SdchManager::GetAvailDictionaryList(const GURL& target_url, + std::string* list) { + DCHECK(thread_checker_.CalledOnValidThread()); + int count = 0; + for (DictionaryMap::iterator it = dictionaries_.begin(); + it != dictionaries_.end(); ++it) { + if (!IsInSupportedDomain(target_url)) + continue; + if (!it->second->CanAdvertise(target_url)) + continue; + ++count; + if (!list->empty()) + list->append(","); + list->append(it->second->client_hash()); + } + // Watch to see if we have corrupt or numerous dictionaries. + if (count > 0) + UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); +} + +// static +void SdchManager::GenerateHash(const std::string& dictionary_text, + std::string* client_hash, std::string* server_hash) { + char binary_hash[32]; + crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); + + std::string first_48_bits(&binary_hash[0], 6); + std::string second_48_bits(&binary_hash[6], 6); + UrlSafeBase64Encode(first_48_bits, client_hash); + UrlSafeBase64Encode(second_48_bits, server_hash); + + DCHECK_EQ(server_hash->length(), 8u); + DCHECK_EQ(client_hash->length(), 8u); +} + +//------------------------------------------------------------------------------ +// Methods for supporting latency experiments. + +bool SdchManager::AllowLatencyExperiment(const GURL& url) const { + DCHECK(thread_checker_.CalledOnValidThread()); + return allow_latency_experiment_.end() != + allow_latency_experiment_.find(url.host()); +} + +void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (enable) { + allow_latency_experiment_.insert(url.host()); + return; + } + ExperimentSet::iterator it = allow_latency_experiment_.find(url.host()); + if (allow_latency_experiment_.end() == it) + return; // It was already erased, or never allowed. + SdchErrorRecovery(LATENCY_TEST_DISALLOWED); + allow_latency_experiment_.erase(it); +} + +void SdchManager::AddObserver(SdchObserver* observer) { + observers_.AddObserver(observer); +} + +void SdchManager::RemoveObserver(SdchObserver* observer) { + observers_.RemoveObserver(observer); +} + +void SdchManager::AddSdchDictionary(const std::string& dictionary_text, const GURL& dictionary_url) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); std::string client_hash; std::string server_hash; GenerateHash(dictionary_text, &client_hash, &server_hash); if (dictionaries_.find(server_hash) != dictionaries_.end()) { SdchErrorRecovery(DICTIONARY_ALREADY_LOADED); - return false; // Already loaded. + return; // Already loaded. } std::string domain, path; @@ -395,13 +519,13 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, if (dictionary_text.empty()) { SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT); - return false; // Missing header. + return; // Missing header. } size_t header_end = dictionary_text.find("\n\n"); if (std::string::npos == header_end) { SdchErrorRecovery(DICTIONARY_HAS_NO_HEADER); - return false; // Missing header. + return; // Missing header. } size_t line_start = 0; // Start of line being parsed. while (1) { @@ -412,7 +536,7 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, size_t colon_index = dictionary_text.find(':', line_start); if (std::string::npos == colon_index) { SdchErrorRecovery(DICTIONARY_HEADER_LINE_MISSING_COLON); - return false; // Illegal line missing a colon. + return; // Illegal line missing a colon. } if (colon_index > line_end) @@ -425,14 +549,14 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, break; std::string name(dictionary_text, line_start, colon_index - line_start); std::string value(dictionary_text, value_start, line_end - value_start); - name = StringToLowerASCII(name); + name = base::StringToLowerASCII(name); if (name == "domain") { domain = value; } else if (name == "path") { path = value; } else if (name == "format-version") { if (value != "1.0") - return false; + return; } else if (name == "max-age") { int64 seconds; base::StringToInt64(value, &seconds); @@ -450,11 +574,15 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, line_start = line_end + 1; } - if (!IsInSupportedDomain(dictionary_url)) - return false; + // Narrow fix for http://crbug.com/389451. + GURL dictionary_url_normalized(dictionary_url); + StripTrailingDot(&dictionary_url_normalized); - if (!Dictionary::CanSet(domain, path, ports, dictionary_url)) - return false; + if (!IsInSupportedDomain(dictionary_url_normalized)) + return; + + if (!Dictionary::CanSet(domain, path, ports, dictionary_url_normalized)) + return; // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of // useless dictionaries. We should probably have a cache eviction plan, @@ -462,11 +590,11 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, // is probably not worth doing eviction handling. if (kMaxDictionarySize < dictionary_text.size()) { SdchErrorRecovery(DICTIONARY_IS_TOO_LARGE); - return false; + return; } if (kMaxDictionaryCount <= dictionaries_.size()) { SdchErrorRecovery(DICTIONARY_COUNT_EXCEEDED); - return false; + return; } UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); @@ -474,87 +602,10 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, << " and server hash " << server_hash; Dictionary* dictionary = new Dictionary(dictionary_text, header_end + 2, client_hash, - dictionary_url, domain, path, expiration, ports); + dictionary_url_normalized, domain, + path, expiration, ports); dictionaries_[server_hash] = dictionary; - return true; -} - -void SdchManager::GetVcdiffDictionary( - const std::string& server_hash, - const GURL& referring_url, - scoped_refptr<Dictionary>* dictionary) { - DCHECK(CalledOnValidThread()); - *dictionary = NULL; - DictionaryMap::iterator it = dictionaries_.find(server_hash); - if (it == dictionaries_.end()) { - return; - } - scoped_refptr<Dictionary> matching_dictionary = it->second; - if (!IsInSupportedDomain(referring_url)) - return; - if (!matching_dictionary->CanUse(referring_url)) - return; - *dictionary = matching_dictionary; -} - -// TODO(jar): If we have evictions from the dictionaries_, then we need to -// change this interface to return a list of reference counted Dictionary -// instances that can be used if/when a server specifies one. -void SdchManager::GetAvailDictionaryList(const GURL& target_url, - std::string* list) { - DCHECK(CalledOnValidThread()); - int count = 0; - for (DictionaryMap::iterator it = dictionaries_.begin(); - it != dictionaries_.end(); ++it) { - if (!IsInSupportedDomain(target_url)) - continue; - if (!it->second->CanAdvertise(target_url)) - continue; - ++count; - if (!list->empty()) - list->append(","); - list->append(it->second->client_hash()); - } - // Watch to see if we have corrupt or numerous dictionaries. - if (count > 0) - UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); -} - -// static -void SdchManager::GenerateHash(const std::string& dictionary_text, - std::string* client_hash, std::string* server_hash) { - char binary_hash[32]; - crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); - - std::string first_48_bits(&binary_hash[0], 6); - std::string second_48_bits(&binary_hash[6], 6); - UrlSafeBase64Encode(first_48_bits, client_hash); - UrlSafeBase64Encode(second_48_bits, server_hash); - - DCHECK_EQ(server_hash->length(), 8u); - DCHECK_EQ(client_hash->length(), 8u); -} - -//------------------------------------------------------------------------------ -// Methods for supporting latency experiments. - -bool SdchManager::AllowLatencyExperiment(const GURL& url) const { - DCHECK(CalledOnValidThread()); - return allow_latency_experiment_.end() != - allow_latency_experiment_.find(url.host()); -} - -void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { - DCHECK(CalledOnValidThread()); - if (enable) { - allow_latency_experiment_.insert(url.host()); - return; - } - ExperimentSet::iterator it = allow_latency_experiment_.find(url.host()); - if (allow_latency_experiment_.end() == it) - return; // It was already erased, or never allowed. - SdchErrorRecovery(LATENCY_TEST_DISALLOWED); - allow_latency_experiment_.erase(it); + return; } // static @@ -563,18 +614,8 @@ void SdchManager::UrlSafeBase64Encode(const std::string& input, // Since this is only done during a dictionary load, and hashes are only 8 // characters, we just do the simple fixup, rather than rewriting the encoder. base::Base64Encode(input, output); - for (size_t i = 0; i < output->size(); ++i) { - switch (output->data()[i]) { - case '+': - (*output)[i] = '-'; - continue; - case '/': - (*output)[i] = '_'; - continue; - default: - continue; - } - } + std::replace(output->begin(), output->end(), '+', '-'); + std::replace(output->begin(), output->end(), '/', '_'); } } // namespace net diff --git a/chromium/net/base/sdch_manager.h b/chromium/net/base/sdch_manager.h index 6f2ea5af6de..ff157e52a32 100644 --- a/chromium/net/base/sdch_manager.h +++ b/chromium/net/base/sdch_manager.h @@ -2,21 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Provides global database of differential decompression dictionaries for the -// SDCH filter (processes sdch enconded content). - -// Exactly one instance of SdchManager is built, and all references are made -// into that collection. -// -// The SdchManager maintains a collection of memory resident dictionaries. It -// can find a dictionary (based on a server specification of a hash), store a -// dictionary, and make judgements about what URLs can use, set, etc. a -// dictionary. - -// These dictionaries are acquired over the net, and include a header -// (containing metadata) as well as a VCDIFF dictionary (for use by a VCDIFF -// module) to decompress data. - #ifndef NET_BASE_SDCH_MANAGER_H_ #define NET_BASE_SDCH_MANAGER_H_ @@ -27,40 +12,28 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/threading/non_thread_safe.h" +#include "base/observer_list.h" +#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "url/gurl.h" namespace net { -//------------------------------------------------------------------------------ -// Create a public interface to help us load SDCH dictionaries. -// The SdchManager class allows registration to support this interface. -// A browser may register a fetcher that is used by the dictionary managers to -// get data from a specified URL. This allows us to use very high level browser -// functionality in this base (when the functionaity can be provided). -class NET_EXPORT SdchFetcher { - public: - SdchFetcher() {} - virtual ~SdchFetcher() {} - - // The Schedule() method is called when there is a need to get a dictionary - // from a server. The callee is responsible for getting that dictionary_text, - // and then calling back to AddSdchDictionary() to the SdchManager instance. - virtual void Schedule(const GURL& dictionary_url) = 0; - - // The Cancel() method is called to cancel all pending dictionary fetches. - // This is used for implementation of ClearData() below. - virtual void Cancel() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(SdchFetcher); -}; +class SdchObserver; -//------------------------------------------------------------------------------ +// Provides global database of differential decompression dictionaries for the +// SDCH filter (processes sdch enconded content). +// +// The SdchManager maintains a collection of memory resident dictionaries. It +// can find a dictionary (based on a server specification of a hash), store a +// dictionary, and make judgements about what URLs can use, set, etc. a +// dictionary. -class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { +// These dictionaries are acquired over the net, and include a header +// (containing metadata) as well as a VCDIFF dictionary (for use by a VCDIFF +// module) to decompress data. +class NET_EXPORT SdchManager { public: // A list of errors that appeared and were either resolved, or used to turn // off sdch encoding. @@ -111,6 +84,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { DICTIONARY_COUNT_EXCEEDED = 35, DICTIONARY_ALREADY_SCHEDULED_TO_DOWNLOAD = 36, DICTIONARY_ALREADY_TRIED_TO_DOWNLOAD = 37, + DICTIONARY_FETCH_READ_FAILED = 38, // Failsafe hack. ATTEMPT_TO_DECODE_NON_HTTP_DATA = 40, @@ -127,7 +101,8 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { META_REFRESH_RECOVERY = 70, // Dictionary not found. // defunct = 71, // Almost the same as META_REFRESH_UNSUPPORTED. // defunct = 72, // Almost the same as CACHED_META_REFRESH_UNSUPPORTED. - // defunct = 73, // PASSING_THROUGH_NON_SDCH plus DISCARD_TENTATIVE_SDCH. + // defunct = 73, // PASSING_THROUGH_NON_SDCH plus + // RESPONSE_TENTATIVE_SDCH in ../filter/sdch_filter.cc. META_REFRESH_UNSUPPORTED = 74, // Unrecoverable error. CACHED_META_REFRESH_UNSUPPORTED = 75, // As above, but pulled from cache. PASSING_THROUGH_NON_SDCH = 76, // Tagged sdch but missing dictionary-hash. @@ -140,7 +115,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Common decoded recovery methods. META_REFRESH_CACHED_RECOVERY = 80, // Probably startup tab loading. - DISCARD_TENTATIVE_SDCH = 81, // Server decided not to use sdch. + // defunct = 81, // Now tracked by ResponseCorruptionDetectionCause histo. // Non SDCH problems, only accounted for to make stat counting complete // (i.e., be able to be sure all dictionary advertisements are accounted @@ -178,7 +153,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { FRIEND_TEST_ALL_PREFIXES(SdchManagerTest, PathMatch); // Construct a vc-diff usable dictionary from the dictionary_text starting - // at the given offset. The supplied client_hash should be used to + // at the given offset. The supplied client_hash should be used to // advertise the dictionary's availability relative to the suppplied URL. Dictionary(const std::string& dictionary_text, size_t offset, @@ -188,7 +163,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { const std::string& path, const base::Time& expiration, const std::set<int>& ports); - ~Dictionary(); + virtual ~Dictionary(); const GURL& url() const { return url_; } const std::string& client_hash() const { return client_hash_; } @@ -227,7 +202,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Metadate "headers" in before dictionary text contained the following: // Each dictionary payload consists of several headers, followed by the text - // of the dictionary. The following are the known headers. + // of the dictionary. The following are the known headers. const std::string domain_; const std::string path_; const base::Time expiration_; // Implied by max-age. @@ -245,9 +220,6 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Record stats on various errors. static void SdchErrorRecovery(ProblemCodes problem); - // Register a fetcher that this class can use to obtain dictionaries. - void set_sdch_fetcher(SdchFetcher* fetcher); - // Enables or disables SDCH compression. static void EnableSdchSupport(bool enabled); @@ -260,16 +232,16 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Briefly prevent further advertising of SDCH on this domain (if SDCH is // enabled). After enough calls to IsInSupportedDomain() the blacklisting - // will be removed. Additional blacklists take exponentially more calls + // will be removed. Additional blacklists take exponentially more calls // to IsInSupportedDomain() before the blacklisting is undone. // Used when filter errors are found from a given domain, but it is plausible // that the cause is temporary (such as application startup, where cached // entries are used, but a dictionary is not yet loaded). - void BlacklistDomain(const GURL& url); + void BlacklistDomain(const GURL& url, ProblemCodes blacklist_reason); // Used when SEVERE filter errors are found from a given domain, to prevent // further use of SDCH on that domain. - void BlacklistDomainForever(const GURL& url); + void BlacklistDomainForever(const GURL& url, ProblemCodes blacklist_reason); // Unit test only, this function resets enabling of sdch, and clears the // blacklist. @@ -286,30 +258,17 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Check to see if SDCH is enabled (globally), and the given URL is in a // supported domain (i.e., not blacklisted, and either the specific supported - // domain, or all domains were assumed supported). If it is blacklist, reduce + // domain, or all domains were assumed supported). If it is blacklist, reduce // by 1 the number of times it will be reported as blacklisted. bool IsInSupportedDomain(const GURL& url); - // Schedule the URL fetching to load a dictionary. This will always return - // before the dictionary is actually loaded and added. - // After the implied task does completes, the dictionary will have been - // cached in memory. - void FetchDictionary(const GURL& request_url, const GURL& dictionary_url); - - // Security test function used before initiating a FetchDictionary. - // Return true if fetch is legal. - bool CanFetchDictionary(const GURL& referring_url, - const GURL& dictionary_url) const; - - // Add an SDCH dictionary to our list of availible dictionaries. This addition - // will fail (return false) if addition is illegal (data in the dictionary is - // not acceptable from the dictionary_url; dictionary already added, etc.). - bool AddSdchDictionary(const std::string& dictionary_text, - const GURL& dictionary_url); + // Send out appropriate events notifying observers that a Get-Dictionary + // header has been seen. + void OnGetDictionary(const GURL& request_url, const GURL& dictionary_url); // Find the vcdiff dictionary (the body of the sdch dictionary that appears // after the meta-data headers like Domain:...) with the given |server_hash| - // to use to decompreses data that arrived as SDCH encoded content. Check to + // to use to decompreses data that arrived as SDCH encoded content. Check to // be sure the returned |dictionary| can be used for decoding content supplied // in response to a request for |referring_url|. // Return null in |dictionary| if there is no matching legal dictionary. @@ -318,28 +277,56 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { scoped_refptr<Dictionary>* dictionary); // Get list of available (pre-cached) dictionaries that we have already loaded - // into memory. The list is a comma separated list of (client) hashes per + // into memory. The list is a comma separated list of (client) hashes per // the SDCH spec. void GetAvailDictionaryList(const GURL& target_url, std::string* list); // Construct the pair of hashes for client and server to identify an SDCH - // dictionary. This is only made public to facilitate unit testing, but is + // dictionary. This is only made public to facilitate unit testing, but is // otherwise private static void GenerateHash(const std::string& dictionary_text, std::string* client_hash, std::string* server_hash); // For Latency testing only, we need to know if we've succeeded in doing a - // round trip before starting our comparative tests. If ever we encounter + // round trip before starting our comparative tests. If ever we encounter // problems with SDCH, we opt-out of the test unless/until we perform a // complete SDCH decoding. bool AllowLatencyExperiment(const GURL& url) const; void SetAllowLatencyExperiment(const GURL& url, bool enable); + // Add an SDCH dictionary to our list of availible + // dictionaries. This addition will fail if addition is illegal + // (data in the dictionary is not acceptable from the + // dictionary_url; dictionary already added, etc.). + void AddSdchDictionary(const std::string& dictionary_text, + const GURL& dictionary_url); + + // Registration for events generated by the SDCH subsystem. + void AddObserver(SdchObserver* observer); + void RemoveObserver(SdchObserver* observer); + private: - typedef std::map<std::string, int> DomainCounter; + struct BlacklistInfo { + BlacklistInfo() + : count(0), + exponential_count(0), + reason(MIN_PROBLEM_CODE) {} + + int count; // # of times to refuse SDCH advertisement. + int exponential_count; // Current exponential backoff ratchet. + ProblemCodes reason; // Why domain was blacklisted. + + }; + typedef std::map<std::string, BlacklistInfo> DomainBlacklistInfo; typedef std::set<std::string> ExperimentSet; + // Determines whether a "Get-Dictionary" header is legal (dictionary + // url has appropriate relationship to referrer url) in the SDCH + // protocol. Return true if fetch is legal. + bool CanFetchDictionary(const GURL& referring_url, + const GURL& dictionary_url) const; + // A map of dictionaries info indexed by the hash that the server provides. typedef std::map<std::string, scoped_refptr<Dictionary> > DictionaryMap; @@ -355,21 +342,21 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { std::string* output); DictionaryMap dictionaries_; - // An instance that can fetch a dictionary given a URL. - scoped_ptr<SdchFetcher> fetcher_; - - // List domains where decode failures have required disabling sdch, along with - // count of how many additonal uses should be blacklisted. - DomainCounter blacklisted_domains_; - - // Support exponential backoff in number of domain accesses before - // blacklisting expires. - DomainCounter exponential_blacklist_count_; + // List domains where decode failures have required disabling sdch. + DomainBlacklistInfo blacklisted_domains_; // List of hostnames for which a latency experiment is allowed (because a // round trip test has recently passed). ExperimentSet allow_latency_experiment_; + // Observers that want to be notified of SDCH events. + // Assert list is empty on destruction since if there is an observer + // that hasn't removed itself from the list, that observer probably + // has a reference to the SdchManager. + ObserverList<SdchObserver, true> observers_; + + base::ThreadChecker thread_checker_; + DISALLOW_COPY_AND_ASSIGN(SdchManager); }; diff --git a/chromium/net/base/sdch_manager_unittest.cc b/chromium/net/base/sdch_manager_unittest.cc index 87b01f4f7ae..d986879aaa4 100644 --- a/chromium/net/base/sdch_manager_unittest.cc +++ b/chromium/net/base/sdch_manager_unittest.cc @@ -9,7 +9,9 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "net/base/sdch_manager.h" +#include "net/base/sdch_observer.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" namespace net { @@ -21,25 +23,72 @@ static const char kTestVcdiffDictionary[] = "DictionaryFor" //------------------------------------------------------------------------------ +class MockSdchObserver : public SdchObserver { + public: + MockSdchObserver() : get_dictionary_notifications_(0) {} + + const GURL& last_dictionary_request_url() { + return last_dictionary_request_url_; + } + const GURL& last_dictionary_url() { return last_dictionary_url_; } + int get_dictionary_notifications() { return get_dictionary_notifications_; } + + // SdchObserver implementation + void OnGetDictionary(SdchManager* manager, + const GURL& request_url, + const GURL& dictionary_url) override { + ++get_dictionary_notifications_; + last_dictionary_request_url_ = request_url; + last_dictionary_url_ = dictionary_url; + } + void OnClearDictionaries(SdchManager* manager) override {} + + private: + int get_dictionary_notifications_; + GURL last_dictionary_request_url_; + GURL last_dictionary_url_; +}; + class SdchManagerTest : public testing::Test { protected: SdchManagerTest() - : sdch_manager_(new SdchManager) { + : sdch_manager_(new SdchManager), + default_support_(false), + default_https_support_(false) { + default_support_ = sdch_manager_->sdch_enabled(); + default_https_support_ = sdch_manager_->secure_scheme_supported(); } + virtual ~SdchManagerTest() {} + SdchManager* sdch_manager() { return sdch_manager_.get(); } // Reset globals back to default state. - virtual void TearDown() { - SdchManager::EnableSdchSupport(true); - SdchManager::EnableSecureSchemeSupport(false); + void TearDown() override { + SdchManager::EnableSdchSupport(default_support_); + SdchManager::EnableSecureSchemeSupport(default_https_support_); + } + + // Attempt to add a dictionary to the manager and probe for success or + // failure. + bool AddSdchDictionary(const std::string& dictionary_text, + const GURL& gurl) { + std::string list; + sdch_manager_->GetAvailDictionaryList(gurl, &list); + sdch_manager_->AddSdchDictionary(dictionary_text, gurl); + std::string list2; + sdch_manager_->GetAvailDictionaryList(gurl, &list2); + + // The list of hashes should change iff the addition succeeds. + return (list != list2); } private: scoped_ptr<SdchManager> sdch_manager_; + bool default_support_; + bool default_https_support_; }; -//------------------------------------------------------------------------------ static std::string NewSdchDictionary(const std::string& domain) { std::string dictionary; if (!domain.empty()) { @@ -65,11 +114,11 @@ TEST_F(SdchManagerTest, DomainBlacklisting) { GURL test_url("http://www.test.com"); GURL google_url("http://www.google.com"); - sdch_manager()->BlacklistDomain(test_url); + sdch_manager()->BlacklistDomain(test_url, SdchManager::MIN_PROBLEM_CODE); EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test_url)); EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url)); - sdch_manager()->BlacklistDomain(google_url); + sdch_manager()->BlacklistDomain(google_url, SdchManager::MIN_PROBLEM_CODE); EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url)); } @@ -79,7 +128,7 @@ TEST_F(SdchManagerTest, DomainBlacklistingCaseSensitivity) { EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test_url)); EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test2_url)); - sdch_manager()->BlacklistDomain(test_url); + sdch_manager()->BlacklistDomain(test_url, SdchManager::MIN_PROBLEM_CODE); EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test2_url)); } @@ -98,7 +147,7 @@ TEST_F(SdchManagerTest, BlacklistingSingleBlacklist) { std::string domain(gurl.host()); sdch_manager()->ClearBlacklistings(); - sdch_manager()->BlacklistDomain(gurl); + sdch_manager()->BlacklistDomain(gurl, SdchManager::MIN_PROBLEM_CODE); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), 1); EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), 1); @@ -115,7 +164,7 @@ TEST_F(SdchManagerTest, BlacklistingExponential) { int exponential = 1; for (int i = 1; i < 100; ++i) { - sdch_manager()->BlacklistDomain(gurl); + sdch_manager()->BlacklistDomain(gurl, SdchManager::MIN_PROBLEM_CODE); EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain), exponential); EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain), exponential); @@ -140,16 +189,16 @@ TEST_F(SdchManagerTest, CanSetExactMatchDictionary) { std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Perfect match should work. - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); } TEST_F(SdchManagerTest, CanAdvertiseDictionaryOverHTTP) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); std::string dictionary_list; // HTTP target URL can advertise dictionary. @@ -163,8 +212,8 @@ TEST_F(SdchManagerTest, CanNotAdvertiseDictionaryOverHTTPS) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); std::string dictionary_list; // HTTPS target URL should NOT advertise dictionary. @@ -178,11 +227,12 @@ TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - EXPECT_FALSE(sdch_manager()->AddSdchDictionary( - dictionary_text, GURL("https://" + dictionary_domain))); + SdchManager::EnableSecureSchemeSupport(false); + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("https://" + dictionary_domain))); SdchManager::EnableSecureSchemeSupport(true); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary( - dictionary_text, GURL("https://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("https://" + dictionary_domain))); GURL target_url("https://" + dictionary_domain + "/test"); std::string dictionary_list; @@ -197,15 +247,15 @@ TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) { std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); - EXPECT_TRUE(dictionary != NULL); + EXPECT_TRUE(dictionary.get() != NULL); } TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) { std::string dictionary_domain("x.y.z.google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); GURL target_url("https://" + dictionary_domain + "/test"); std::string dictionary_list; @@ -220,7 +270,30 @@ TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) { std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); - EXPECT_TRUE(dictionary == NULL); + EXPECT_TRUE(dictionary.get() == NULL); +} + +TEST_F(SdchManagerTest, CanNotUseHTTPSDictionaryOverHTTP) { + std::string dictionary_domain("x.y.z.google.com"); + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + + SdchManager::EnableSecureSchemeSupport(true); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("https://" + dictionary_domain))); + + GURL target_url("http://" + dictionary_domain + "/test"); + std::string dictionary_list; + // HTTP target URL should not advertise dictionary acquired over HTTPS even if + // secure scheme support is enabled. + sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list); + EXPECT_TRUE(dictionary_list.empty()); + + scoped_refptr<SdchManager::Dictionary> dictionary; + std::string client_hash; + std::string server_hash; + sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); + sdch_manager()->GetVcdiffDictionary(server_hash, target_url, &dictionary); + EXPECT_TRUE(dictionary.get() == NULL); } TEST_F(SdchManagerTest, FailToSetDomainMismatchDictionary) { @@ -228,8 +301,8 @@ TEST_F(SdchManagerTest, FailToSetDomainMismatchDictionary) { std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the "domain match" requirement. - EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://y.z.google.com"))); + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://y.z.google.com"))); } TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionary) { @@ -237,8 +310,17 @@ TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionary) { std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the HD with D being the domain and H having a dot requirement. - EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://w.x.y.z.google.com"))); + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://w.x.y.z.google.com"))); +} + +TEST_F(SdchManagerTest, FailToSetDotHostPrefixDomainDictionaryTrailingDot) { + std::string dictionary_domain("x.y.z.google.com"); + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + + // Fail the HD with D being the domain and H having a dot requirement. + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://w.x.y.z.google.com."))); } TEST_F(SdchManagerTest, FailToSetRepeatPrefixWithDotDictionary) { @@ -248,8 +330,8 @@ TEST_F(SdchManagerTest, FailToSetRepeatPrefixWithDotDictionary) { std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Fail the HD with D being the domain and H having a dot requirement. - EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com.www.google.com"))); + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://www.google.com.www.google.com"))); } TEST_F(SdchManagerTest, CanSetLeadingDotDomainDictionary) { @@ -260,8 +342,43 @@ TEST_F(SdchManagerTest, CanSetLeadingDotDomainDictionary) { // Verify that a leading dot in the domain is acceptable, as long as the host // name does not contain any dots preceding the matched domain name. - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com"))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, GURL("http://www.google.com"))); +} + +TEST_F(SdchManagerTest, + CanSetLeadingDotDomainDictionaryFromURLWithTrailingDot) { + // Make sure that a prefix that matches the domain postfix won't confuse + // the validation checks. + std::string dictionary_domain(".google.com"); + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + + // Verify that a leading dot in the domain is acceptable, as long as the host + // name does not contain any dots preceding the matched domain name. + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://www.google.com."))); +} + +TEST_F(SdchManagerTest, CannotSetLeadingDotDomainDictionary) { + // Make sure that a prefix that matches the domain postfix won't confuse + // the validation checks. + std::string dictionary_domain(".google.com"); + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + + // Verify that a leading dot in the domain does not affect the name containing + // dots failure. + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://www.subdomain.google.com"))); +} + +TEST_F(SdchManagerTest, CannotSetLeadingDotDomainDictionaryTrailingDot) { + // Make sure that a prefix that matches the domain postfix won't confuse + // the validation checks. + std::string dictionary_domain(".google.com"); + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + + // Verify that a trailing period in the URL doesn't affect the check. + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://www.subdomain.google.com."))); } // Make sure the order of the tests is not helping us or confusing things. @@ -271,8 +388,8 @@ TEST_F(SdchManagerTest, CanStillSetExactMatchDictionary) { std::string dictionary_text(NewSdchDictionary(dictionary_domain)); // Perfect match should *STILL* work. - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); } // Make sure the DOS protection precludes the addition of too many dictionaries. @@ -280,16 +397,13 @@ TEST_F(SdchManagerTest, TooManyDictionaries) { std::string dictionary_domain(".google.com"); std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - size_t count = 0; - while (count <= SdchManager::kMaxDictionaryCount + 1) { - if (!sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com"))) - break; - + for (size_t count = 0; count < SdchManager::kMaxDictionaryCount; ++count) { + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://www.google.com"))); dictionary_text += " "; // Create dictionary with different SHA signature. - ++count; } - EXPECT_EQ(SdchManager::kMaxDictionaryCount, count); + EXPECT_FALSE( + AddSdchDictionary(dictionary_text, GURL("http://www.google.com"))); } TEST_F(SdchManagerTest, DictionaryNotTooLarge) { @@ -298,8 +412,8 @@ TEST_F(SdchManagerTest, DictionaryNotTooLarge) { dictionary_text.append( SdchManager::kMaxDictionarySize - dictionary_text.size(), ' '); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); } TEST_F(SdchManagerTest, DictionaryTooLarge) { @@ -308,8 +422,8 @@ TEST_F(SdchManagerTest, DictionaryTooLarge) { dictionary_text.append( SdchManager::kMaxDictionarySize + 1 - dictionary_text.size(), ' '); - EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); + EXPECT_FALSE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); } TEST_F(SdchManagerTest, PathMatch) { @@ -399,46 +513,50 @@ TEST_F(SdchManagerTest, CanUseMultipleManagers) { // Confirm that if you add directories to one manager, you // can't get them from the other. - EXPECT_TRUE(sdch_manager()->AddSdchDictionary( - dictionary_text_1, GURL("http://" + dictionary_domain_1))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text_1, + GURL("http://" + dictionary_domain_1))); scoped_refptr<SdchManager::Dictionary> dictionary; sdch_manager()->GetVcdiffDictionary( server_hash_1, GURL("http://" + dictionary_domain_1 + "/random_url"), &dictionary); - EXPECT_TRUE(dictionary); + EXPECT_TRUE(dictionary.get()); - EXPECT_TRUE(second_manager.AddSdchDictionary( - dictionary_text_2, GURL("http://" + dictionary_domain_2))); + second_manager.AddSdchDictionary( + dictionary_text_2, GURL("http://" + dictionary_domain_2)); second_manager.GetVcdiffDictionary( server_hash_2, GURL("http://" + dictionary_domain_2 + "/random_url"), &dictionary); - EXPECT_TRUE(dictionary); + EXPECT_TRUE(dictionary.get()); sdch_manager()->GetVcdiffDictionary( server_hash_2, GURL("http://" + dictionary_domain_2 + "/random_url"), &dictionary); - EXPECT_FALSE(dictionary); + EXPECT_FALSE(dictionary.get()); second_manager.GetVcdiffDictionary( server_hash_1, GURL("http://" + dictionary_domain_1 + "/random_url"), &dictionary); - EXPECT_FALSE(dictionary); + EXPECT_FALSE(dictionary.get()); } TEST_F(SdchManagerTest, HttpsCorrectlySupported) { GURL url("http://www.google.com"); GURL secure_url("https://www.google.com"); + bool expect_https_support = true; + EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url)); - EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(secure_url)); + EXPECT_EQ(expect_https_support, + sdch_manager()->IsInSupportedDomain(secure_url)); - SdchManager::EnableSecureSchemeSupport(true); + SdchManager::EnableSecureSchemeSupport(!expect_https_support); EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url)); - EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(secure_url)); + EXPECT_NE(expect_https_support, + sdch_manager()->IsInSupportedDomain(secure_url)); } TEST_F(SdchManagerTest, ClearDictionaryData) { @@ -451,16 +569,17 @@ TEST_F(SdchManagerTest, ClearDictionaryData) { SdchManager::GenerateHash(dictionary_text, &tmp_hash, &server_hash); - EXPECT_TRUE(sdch_manager()->AddSdchDictionary( - dictionary_text, GURL("http://" + dictionary_domain))); + EXPECT_TRUE(AddSdchDictionary(dictionary_text, + GURL("http://" + dictionary_domain))); scoped_refptr<SdchManager::Dictionary> dictionary; sdch_manager()->GetVcdiffDictionary( server_hash, GURL("http://" + dictionary_domain + "/random_url"), &dictionary); - EXPECT_TRUE(dictionary); + EXPECT_TRUE(dictionary.get()); - sdch_manager()->BlacklistDomain(GURL(blacklist_url)); + sdch_manager()->BlacklistDomain(GURL(blacklist_url), + SdchManager::MIN_PROBLEM_CODE); EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(blacklist_url)); sdch_manager()->ClearData(); @@ -470,9 +589,27 @@ TEST_F(SdchManagerTest, ClearDictionaryData) { server_hash, GURL("http://" + dictionary_domain + "/random_url"), &dictionary); - EXPECT_FALSE(dictionary); + EXPECT_FALSE(dictionary.get()); EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(blacklist_url)); } -} // namespace net +TEST_F(SdchManagerTest, GetDictionaryNotification) { + GURL test_request_gurl(GURL("http://www.example.com/data")); + GURL test_dictionary_gurl(GURL("http://www.example.com/dict")); + MockSdchObserver observer; + sdch_manager()->AddObserver(&observer); + + EXPECT_EQ(0, observer.get_dictionary_notifications()); + sdch_manager()->OnGetDictionary(test_request_gurl, test_dictionary_gurl); + EXPECT_EQ(1, observer.get_dictionary_notifications()); + EXPECT_EQ(test_request_gurl, observer.last_dictionary_request_url()); + EXPECT_EQ(test_dictionary_gurl, observer.last_dictionary_url()); + + sdch_manager()->RemoveObserver(&observer); + sdch_manager()->OnGetDictionary(test_request_gurl, test_dictionary_gurl); + EXPECT_EQ(1, observer.get_dictionary_notifications()); + EXPECT_EQ(test_request_gurl, observer.last_dictionary_request_url()); + EXPECT_EQ(test_dictionary_gurl, observer.last_dictionary_url()); +} +} // namespace net diff --git a/chromium/net/base/sdch_observer.cc b/chromium/net/base/sdch_observer.cc new file mode 100644 index 00000000000..9bf44addd68 --- /dev/null +++ b/chromium/net/base/sdch_observer.cc @@ -0,0 +1,14 @@ +// Copyright 2014 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 "net/base/sdch_observer.h" + +#include "base/logging.h" +#include "net/base/sdch_manager.h" + +namespace net { + +SdchObserver::~SdchObserver() { +} +} diff --git a/chromium/net/base/sdch_observer.h b/chromium/net/base/sdch_observer.h new file mode 100644 index 00000000000..2c5987d8698 --- /dev/null +++ b/chromium/net/base/sdch_observer.h @@ -0,0 +1,34 @@ +// Copyright 2014 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 NET_BASE_SDCH_OBSERVER_H_ +#define NET_BASE_SDCH_OBSERVER_H_ + +#include "net/base/net_export.h" + +class GURL; + +namespace net { + +class SdchManager; + +// Observer interface for SDCH. Observers can register with +// the SdchManager to receive notifications of various SDCH events. +class NET_EXPORT SdchObserver { + public: + virtual ~SdchObserver(); + + // Notification that SDCH has seen a "Get-Dictionary" header. + virtual void OnGetDictionary(SdchManager* manager, + const GURL& request_url, + const GURL& dictionary_url) = 0; + + // Notification that SDCH has received a request to clear all + // its dictionaries. + virtual void OnClearDictionaries(SdchManager* manager) = 0; +}; + +} // namespace net + +#endif // NET_BASE_SDCH_MANAGER_H_ diff --git a/chromium/net/base/test_completion_callback.cc b/chromium/net/base/test_completion_callback.cc index 4fcff74faac..7094592d1dd 100644 --- a/chromium/net/base/test_completion_callback.cc +++ b/chromium/net/base/test_completion_callback.cc @@ -35,11 +35,21 @@ TestCompletionCallbackBaseInternal::TestCompletionCallbackBaseInternal() waiting_for_result_(false) { } +TestCompletionCallbackBaseInternal::~TestCompletionCallbackBaseInternal() { +} + } // namespace internal +TestClosure::TestClosure() + : closure_(base::Bind(&TestClosure::DidSetResult, base::Unretained(this))) { +} + +TestClosure::~TestClosure() { +} + TestCompletionCallback::TestCompletionCallback() : callback_(base::Bind(&TestCompletionCallback::SetResult, - base::Unretained(this))) { + base::Unretained(this))) { } TestCompletionCallback::~TestCompletionCallback() { @@ -47,7 +57,7 @@ TestCompletionCallback::~TestCompletionCallback() { TestInt64CompletionCallback::TestInt64CompletionCallback() : callback_(base::Bind(&TestInt64CompletionCallback::SetResult, - base::Unretained(this))) { + base::Unretained(this))) { } TestInt64CompletionCallback::~TestInt64CompletionCallback() { diff --git a/chromium/net/base/test_completion_callback.h b/chromium/net/base/test_completion_callback.h index 4a0afe13359..c1f715c9dfa 100644 --- a/chromium/net/base/test_completion_callback.h +++ b/chromium/net/base/test_completion_callback.h @@ -5,6 +5,7 @@ #ifndef NET_BASE_TEST_COMPLETION_CALLBACK_H_ #define NET_BASE_TEST_COMPLETION_CALLBACK_H_ +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/tuple.h" #include "net/base/completion_callback.h" @@ -34,6 +35,8 @@ class TestCompletionCallbackBaseInternal { protected: TestCompletionCallbackBaseInternal(); + virtual ~TestCompletionCallbackBaseInternal(); + void DidSetResult(); void WaitForResult(); @@ -48,7 +51,7 @@ template <typename R> class TestCompletionCallbackTemplate : public TestCompletionCallbackBaseInternal { public: - virtual ~TestCompletionCallbackTemplate() {} + virtual ~TestCompletionCallbackTemplate() override {} R WaitForResult() { TestCompletionCallbackBaseInternal::WaitForResult(); @@ -77,6 +80,22 @@ class TestCompletionCallbackTemplate } // namespace internal +class TestClosure + : public internal::TestCompletionCallbackBaseInternal { + public: + using internal::TestCompletionCallbackBaseInternal::WaitForResult; + + TestClosure(); + virtual ~TestClosure() override; + + const base::Closure& closure() const { return closure_; } + + private: + const base::Closure closure_; + + DISALLOW_COPY_AND_ASSIGN(TestClosure); +}; + // Base class overridden by custom implementations of TestCompletionCallback. typedef internal::TestCompletionCallbackTemplate<int> TestCompletionCallbackBase; @@ -87,7 +106,7 @@ typedef internal::TestCompletionCallbackTemplate<int64> class TestCompletionCallback : public TestCompletionCallbackBase { public: TestCompletionCallback(); - virtual ~TestCompletionCallback(); + virtual ~TestCompletionCallback() override; const CompletionCallback& callback() const { return callback_; } @@ -100,7 +119,7 @@ class TestCompletionCallback : public TestCompletionCallbackBase { class TestInt64CompletionCallback : public TestInt64CompletionCallbackBase { public: TestInt64CompletionCallback(); - virtual ~TestInt64CompletionCallback(); + virtual ~TestInt64CompletionCallback() override; const Int64CompletionCallback& callback() const { return callback_; } @@ -114,10 +133,10 @@ class TestInt64CompletionCallback : public TestInt64CompletionCallbackBase { class ReleaseBufferCompletionCallback: public TestCompletionCallback { public: explicit ReleaseBufferCompletionCallback(IOBuffer* buffer); - virtual ~ReleaseBufferCompletionCallback(); + virtual ~ReleaseBufferCompletionCallback() override; private: - virtual void SetResult(int result) OVERRIDE; + void SetResult(int result) override; IOBuffer* buffer_; DISALLOW_COPY_AND_ASSIGN(ReleaseBufferCompletionCallback); diff --git a/chromium/net/base/test_completion_callback_unittest.cc b/chromium/net/base/test_completion_callback_unittest.cc index 704273ebc7f..b0c8565b112 100644 --- a/chromium/net/base/test_completion_callback_unittest.cc +++ b/chromium/net/base/test_completion_callback_unittest.cc @@ -13,10 +13,18 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -typedef PlatformTest TestCompletionCallbackTest; +namespace { const int kMagicResult = 8888; +void CallClosureAfterCheckingResult(const base::Closure& closure, + bool* did_check_result, + int result) { + DCHECK_EQ(result, kMagicResult); + *did_check_result = true; + closure.Run(); +} + // ExampleEmployer is a toy version of HostResolver // TODO: restore damage done in extracting example from real code // (e.g. bring back real destructor, bring back comments) @@ -111,13 +119,32 @@ bool ExampleEmployer::DoSomething(const net::CompletionCallback& callback) { return true; } +} // namespace + +typedef PlatformTest TestCompletionCallbackTest; + TEST_F(TestCompletionCallbackTest, Simple) { ExampleEmployer boss; net::TestCompletionCallback callback; bool queued = boss.DoSomething(callback.callback()); - EXPECT_EQ(queued, true); + EXPECT_TRUE(queued); int result = callback.WaitForResult(); EXPECT_EQ(result, kMagicResult); } +TEST_F(TestCompletionCallbackTest, Closure) { + ExampleEmployer boss; + net::TestClosure closure; + bool did_check_result = false; + net::CompletionCallback completion_callback = + base::Bind(&CallClosureAfterCheckingResult, + closure.closure(), base::Unretained(&did_check_result)); + bool queued = boss.DoSomething(completion_callback); + EXPECT_TRUE(queued); + + EXPECT_FALSE(did_check_result); + closure.WaitForResult(); + EXPECT_TRUE(did_check_result); +} + // TODO: test deleting ExampleEmployer while work outstanding diff --git a/chromium/net/base/trace_net_log_observer.cc b/chromium/net/base/trace_net_log_observer.cc new file mode 100644 index 00000000000..5d98c41d37b --- /dev/null +++ b/chromium/net/base/trace_net_log_observer.cc @@ -0,0 +1,112 @@ +// Copyright 2014 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 "net/base/trace_net_log_observer.h" + +#include <stdio.h> + +#include <string> + +#include "base/debug/trace_event.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "net/base/net_log.h" + +namespace net { + +namespace { + +// TraceLog category for NetLog events. +const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog"); + +class TracedValue : public base::debug::ConvertableToTraceFormat { + public: + explicit TracedValue(scoped_ptr<base::Value> value) : value_(value.Pass()) {} + + private: + ~TracedValue() override {} + + void AppendAsTraceFormat(std::string* out) const override { + if (value_) { + std::string tmp; + base::JSONWriter::Write(value_.get(), &tmp); + *out += tmp; + } else { + *out += "\"\""; + } + } + + private: + scoped_ptr<base::Value> value_; +}; + +} // namespace + +TraceNetLogObserver::TraceNetLogObserver() : net_log_to_watch_(NULL) { +} + +TraceNetLogObserver::~TraceNetLogObserver() { + DCHECK(!net_log_to_watch_); + DCHECK(!net_log()); +} + +void TraceNetLogObserver::OnAddEntry(const NetLog::Entry& entry) { + scoped_ptr<base::Value> params(entry.ParametersToValue()); + switch (entry.phase()) { + case NetLog::PHASE_BEGIN: + TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( + kNetLogTracingCategory, + NetLog::EventTypeToString(entry.type()), entry.source().id, + "source_type", NetLog::SourceTypeToString(entry.source().type), + "params", scoped_refptr<base::debug::ConvertableToTraceFormat>( + new TracedValue(params.Pass()))); + break; + case NetLog::PHASE_END: + TRACE_EVENT_NESTABLE_ASYNC_END2( + kNetLogTracingCategory, + NetLog::EventTypeToString(entry.type()), entry.source().id, + "source_type", NetLog::SourceTypeToString(entry.source().type), + "params", scoped_refptr<base::debug::ConvertableToTraceFormat>( + new TracedValue(params.Pass()))); + break; + case NetLog::PHASE_NONE: + TRACE_EVENT_NESTABLE_ASYNC_INSTANT2( + kNetLogTracingCategory, + NetLog::EventTypeToString(entry.type()), entry.source().id, + "source_type", NetLog::SourceTypeToString(entry.source().type), + "params", scoped_refptr<base::debug::ConvertableToTraceFormat>( + new TracedValue(params.Pass()))); + break; + } +} + +void TraceNetLogObserver::WatchForTraceStart(NetLog* netlog) { + DCHECK(!net_log_to_watch_); + DCHECK(!net_log()); + net_log_to_watch_ = netlog; + base::debug::TraceLog::GetInstance()->AddEnabledStateObserver(this); +} + +void TraceNetLogObserver::StopWatchForTraceStart() { + // Should only stop if is currently watching. + DCHECK(net_log_to_watch_); + base::debug::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); + if (net_log()) + net_log()->RemoveThreadSafeObserver(this); + net_log_to_watch_ = NULL; +} + +void TraceNetLogObserver::OnTraceLogEnabled() { + net_log_to_watch_->AddThreadSafeObserver(this, + NetLog::LOG_STRIP_PRIVATE_DATA); +} + +void TraceNetLogObserver::OnTraceLogDisabled() { + if (net_log()) + net_log()->RemoveThreadSafeObserver(this); +} + +} // namespace net diff --git a/chromium/net/base/trace_net_log_observer.h b/chromium/net/base/trace_net_log_observer.h new file mode 100644 index 00000000000..9fc062b6f91 --- /dev/null +++ b/chromium/net/base/trace_net_log_observer.h @@ -0,0 +1,49 @@ +// Copyright 2014 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 NET_BASE_TRACE_NET_LOG_OBSERVER_H_ +#define NET_BASE_TRACE_NET_LOG_OBSERVER_H_ + +#include "base/debug/trace_event_impl.h" +#include "base/macros.h" +#include "net/base/net_export.h" +#include "net/base/net_log.h" + +namespace net { + +// TraceNetLogObserver watches for TraceLog enable, and sends NetLog +// events to TraceLog if it is enabled. +class NET_EXPORT TraceNetLogObserver + : public NetLog::ThreadSafeObserver, + public base::debug::TraceLog::EnabledStateObserver { + public: + TraceNetLogObserver(); + ~TraceNetLogObserver() override; + + // net::NetLog::ThreadSafeObserver implementation: + void OnAddEntry(const NetLog::Entry& entry) override; + + // Start to watch for TraceLog enable and disable events. + // This can't be called if already watching for events. + // Watches NetLog only when tracing is enabled. + void WatchForTraceStart(NetLog* net_log); + + // Stop watching for TraceLog enable and disable events. + // If WatchForTraceStart is called, this must be called before + // TraceNetLogObserver is destroyed. + void StopWatchForTraceStart(); + + // base::debug::TraceLog::EnabledStateChangedObserver implementation: + void OnTraceLogEnabled() override; + void OnTraceLogDisabled() override; + + private: + NetLog* net_log_to_watch_; + + DISALLOW_COPY_AND_ASSIGN(TraceNetLogObserver); +}; + +} // namespace net + +#endif // NET_BASE_TRACE_NET_LOG_OBSERVER_H_ diff --git a/chromium/net/base/trace_net_log_observer_unittest.cc b/chromium/net/base/trace_net_log_observer_unittest.cc new file mode 100644 index 00000000000..5256bac9c8a --- /dev/null +++ b/chromium/net/base/trace_net_log_observer_unittest.cc @@ -0,0 +1,378 @@ +// Copyright 2014 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 "net/base/trace_net_log_observer.h" + +#include <string> +#include <vector> + +#include "base/debug/trace_event.h" +#include "base/debug/trace_event_impl.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "net/base/capturing_net_log.h" +#include "net/base/net_log.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::debug::TraceLog; + +namespace net { + +namespace { + +// TraceLog category for NetLog events. +const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog"); + +struct TraceEntryInfo { + std::string category; + std::string id; + std::string phase; + std::string name; + std::string source_type; +}; + +TraceEntryInfo GetTraceEntryInfoFromValue(const base::DictionaryValue& value) { + TraceEntryInfo info; + EXPECT_TRUE(value.GetString("cat", &info.category)); + EXPECT_TRUE(value.GetString("id", &info.id)); + EXPECT_TRUE(value.GetString("ph", &info.phase)); + EXPECT_TRUE(value.GetString("name", &info.name)); + EXPECT_TRUE(value.GetString("args.source_type", &info.source_type)); + + return info; +} + +class TraceNetLogObserverTest : public testing::Test { + public: + TraceNetLogObserverTest() { + TraceLog* tracelog = TraceLog::GetInstance(); + DCHECK(tracelog); + DCHECK(!tracelog->IsEnabled()); + trace_buffer_.SetOutputCallback(json_output_.GetCallback()); + trace_net_log_observer_.reset(new TraceNetLogObserver()); + trace_events_.reset(new base::ListValue()); + } + + ~TraceNetLogObserverTest() override { + DCHECK(!TraceLog::GetInstance()->IsEnabled()); + } + + void OnTraceDataCollected( + base::RunLoop* run_loop, + const scoped_refptr<base::RefCountedString>& events_str, + bool has_more_events) { + DCHECK(trace_events_->empty()); + trace_buffer_.Start(); + trace_buffer_.AddFragment(events_str->data()); + trace_buffer_.Finish(); + + scoped_ptr<base::Value> trace_value; + trace_value.reset(base::JSONReader::Read( + json_output_.json_output, + base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN)); + + ASSERT_TRUE(trace_value) << json_output_.json_output; + base::ListValue* trace_events = NULL; + ASSERT_TRUE(trace_value->GetAsList(&trace_events)); + + trace_events_ = FilterNetLogTraceEvents(*trace_events); + + if (!has_more_events) + run_loop->Quit(); + } + + static void EnableTraceLog() { + TraceLog::GetInstance()->SetEnabled( + base::debug::CategoryFilter(kNetLogTracingCategory), + TraceLog::RECORDING_MODE, + base::debug::TraceOptions()); + } + + void EndTraceAndFlush() { + base::RunLoop run_loop; + TraceLog::GetInstance()->SetDisabled(); + TraceLog::GetInstance()->Flush( + base::Bind(&TraceNetLogObserverTest::OnTraceDataCollected, + base::Unretained(this), + base::Unretained(&run_loop))); + run_loop.Run(); + } + + void set_trace_net_log_observer(TraceNetLogObserver* trace_net_log_observer) { + trace_net_log_observer_.reset(trace_net_log_observer); + } + + static scoped_ptr<base::ListValue> FilterNetLogTraceEvents( + const base::ListValue& trace_events) { + scoped_ptr<base::ListValue> filtered_trace_events(new base::ListValue()); + for (size_t i = 0; i < trace_events.GetSize(); i++) { + const base::DictionaryValue* dict = NULL; + if (!trace_events.GetDictionary(i, &dict)) { + ADD_FAILURE() << "Unexpected non-dictionary event in trace_events"; + continue; + } + std::string category; + if (!dict->GetString("cat", &category)) { + ADD_FAILURE() + << "Unexpected item without a category field in trace_events"; + continue; + } + if (category != kNetLogTracingCategory) + continue; + filtered_trace_events->Append(dict->DeepCopy()); + } + return filtered_trace_events.Pass(); + } + + base::ListValue* trace_events() const { + return trace_events_.get(); + } + + CapturingNetLog* net_log() { + return &net_log_; + } + + TraceNetLogObserver* trace_net_log_observer() const { + return trace_net_log_observer_.get(); + } + + private: + scoped_ptr<base::ListValue> trace_events_; + base::debug::TraceResultBuffer trace_buffer_; + base::debug::TraceResultBuffer::SimpleOutput json_output_; + CapturingNetLog net_log_; + scoped_ptr<TraceNetLogObserver> trace_net_log_observer_; +}; + +TEST_F(TraceNetLogObserverTest, TracingNotEnabled) { + trace_net_log_observer()->WatchForTraceStart(net_log()); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + + EndTraceAndFlush(); + trace_net_log_observer()->StopWatchForTraceStart(); + + EXPECT_EQ(0u, trace_events()->GetSize()); +} + +TEST_F(TraceNetLogObserverTest, TraceEventCaptured) { + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_TRUE(entries.empty()); + + trace_net_log_observer()->WatchForTraceStart(net_log()); + EnableTraceLog(); + BoundNetLog bound_net_log = + BoundNetLog::Make(net_log(), net::NetLog::SOURCE_NONE); + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); + bound_net_log.BeginEvent(NetLog::TYPE_URL_REQUEST_START_JOB); + bound_net_log.EndEvent(NetLog::TYPE_REQUEST_ALIVE); + + net_log()->GetEntries(&entries); + EXPECT_EQ(3u, entries.size()); + EndTraceAndFlush(); + trace_net_log_observer()->StopWatchForTraceStart(); + EXPECT_EQ(3u, trace_events()->GetSize()); + const base::DictionaryValue* item1 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); + const base::DictionaryValue* item2 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); + const base::DictionaryValue* item3 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(2, &item3)); + + TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); + TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); + TraceEntryInfo actual_item3 = GetTraceEntryInfoFromValue(*item3); + EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item1.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), + actual_item1.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), + actual_item1.source_type); + + EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN), + actual_item2.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), + actual_item2.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), + actual_item2.source_type); + + EXPECT_EQ(kNetLogTracingCategory, actual_item3.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item3.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END), + actual_item3.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), + actual_item3.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), + actual_item3.source_type); +} + +TEST_F(TraceNetLogObserverTest, EnableAndDisableTracing) { + trace_net_log_observer()->WatchForTraceStart(net_log()); + EnableTraceLog(); + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); + TraceLog::GetInstance()->SetDisabled(); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + EnableTraceLog(); + net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); + + EndTraceAndFlush(); + trace_net_log_observer()->StopWatchForTraceStart(); + + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(3u, entries.size()); + EXPECT_EQ(2u, trace_events()->GetSize()); + const base::DictionaryValue* item1 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); + const base::DictionaryValue* item2 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); + + TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); + TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); + EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item1.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), + actual_item1.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), + actual_item1.source_type); + + EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[2].source.id), actual_item2.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item2.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_URL_REQUEST_START_JOB), + actual_item2.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[2].source.type), + actual_item2.source_type); +} + +TEST_F(TraceNetLogObserverTest, DestroyObserverWhileTracing) { + trace_net_log_observer()->WatchForTraceStart(net_log()); + EnableTraceLog(); + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); + trace_net_log_observer()->StopWatchForTraceStart(); + set_trace_net_log_observer(NULL); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + + EndTraceAndFlush(); + + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(2u, entries.size()); + EXPECT_EQ(1u, trace_events()->GetSize()); + + const base::DictionaryValue* item1 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); + + TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); + EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item1.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), + actual_item1.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), + actual_item1.source_type); +} + +TEST_F(TraceNetLogObserverTest, DestroyObserverWhileNotTracing) { + trace_net_log_observer()->WatchForTraceStart(net_log()); + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); + trace_net_log_observer()->StopWatchForTraceStart(); + set_trace_net_log_observer(NULL); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); + + EndTraceAndFlush(); + + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(3u, entries.size()); + EXPECT_EQ(0u, trace_events()->GetSize()); +} + +TEST_F(TraceNetLogObserverTest, CreateObserverAfterTracingStarts) { + set_trace_net_log_observer(NULL); + EnableTraceLog(); + set_trace_net_log_observer(new TraceNetLogObserver()); + trace_net_log_observer()->WatchForTraceStart(net_log()); + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED); + trace_net_log_observer()->StopWatchForTraceStart(); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + net_log()->AddGlobalEntry(NetLog::TYPE_URL_REQUEST_START_JOB); + + EndTraceAndFlush(); + + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(3u, entries.size()); + EXPECT_EQ(0u, trace_events()->GetSize()); +} + +TEST_F(TraceNetLogObserverTest, EventsWithAndWithoutParameters) { + trace_net_log_observer()->WatchForTraceStart(net_log()); + EnableTraceLog(); + NetLog::ParametersCallback net_log_callback; + std::string param = "bar"; + net_log_callback = NetLog::StringCallback("foo", ¶m); + + net_log()->AddGlobalEntry(NetLog::TYPE_CANCELLED, net_log_callback); + net_log()->AddGlobalEntry(NetLog::TYPE_REQUEST_ALIVE); + + EndTraceAndFlush(); + trace_net_log_observer()->StopWatchForTraceStart(); + + CapturingNetLog::CapturedEntryList entries; + net_log()->GetEntries(&entries); + EXPECT_EQ(2u, entries.size()); + EXPECT_EQ(2u, trace_events()->GetSize()); + const base::DictionaryValue* item1 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(0, &item1)); + const base::DictionaryValue* item2 = NULL; + ASSERT_TRUE(trace_events()->GetDictionary(1, &item2)); + + TraceEntryInfo actual_item1 = GetTraceEntryInfoFromValue(*item1); + TraceEntryInfo actual_item2 = GetTraceEntryInfoFromValue(*item2); + EXPECT_EQ(kNetLogTracingCategory, actual_item1.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[0].source.id), actual_item1.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item1.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_CANCELLED), + actual_item1.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[0].source.type), + actual_item1.source_type); + + EXPECT_EQ(kNetLogTracingCategory, actual_item2.category); + EXPECT_EQ(base::StringPrintf("0x%d", entries[1].source.id), actual_item2.id); + EXPECT_EQ(std::string(1, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT), + actual_item2.phase); + EXPECT_EQ(NetLog::EventTypeToString(NetLog::TYPE_REQUEST_ALIVE), + actual_item2.name); + EXPECT_EQ(NetLog::SourceTypeToString(entries[1].source.type), + actual_item2.source_type); + + std::string item1_params; + std::string item2_params; + EXPECT_TRUE(item1->GetString("args.params.foo", &item1_params)); + EXPECT_EQ("bar", item1_params); + + EXPECT_TRUE(item2->GetString("args.params", &item2_params)); + EXPECT_TRUE(item2_params.empty()); +} + +} // namespace + +} // namespace net diff --git a/chromium/net/base/upload_bytes_element_reader.h b/chromium/net/base/upload_bytes_element_reader.h index 9c7daf3a657..3246d129ed4 100644 --- a/chromium/net/base/upload_bytes_element_reader.h +++ b/chromium/net/base/upload_bytes_element_reader.h @@ -20,20 +20,20 @@ namespace net { class NET_EXPORT UploadBytesElementReader : public UploadElementReader { public: UploadBytesElementReader(const char* bytes, uint64 length); - virtual ~UploadBytesElementReader(); + ~UploadBytesElementReader() override; const char* bytes() const { return bytes_; } uint64 length() const { return length_; } // UploadElementReader overrides: - virtual const UploadBytesElementReader* AsBytesReader() const OVERRIDE; - virtual int Init(const CompletionCallback& callback) OVERRIDE; - virtual uint64 GetContentLength() const OVERRIDE; - virtual uint64 BytesRemaining() const OVERRIDE; - virtual bool IsInMemory() const OVERRIDE; - virtual int Read(IOBuffer* buf, - int buf_length, - const CompletionCallback& callback) OVERRIDE; + const UploadBytesElementReader* AsBytesReader() const override; + int Init(const CompletionCallback& callback) override; + uint64 GetContentLength() const override; + uint64 BytesRemaining() const override; + bool IsInMemory() const override; + int Read(IOBuffer* buf, + int buf_length, + const CompletionCallback& callback) override; private: const char* const bytes_; @@ -49,7 +49,7 @@ class NET_EXPORT UploadOwnedBytesElementReader public: // |data| is cleared by this ctor. explicit UploadOwnedBytesElementReader(std::vector<char>* data); - virtual ~UploadOwnedBytesElementReader(); + ~UploadOwnedBytesElementReader() override; // Creates UploadOwnedBytesElementReader with a string. static UploadOwnedBytesElementReader* CreateWithString( diff --git a/chromium/net/base/upload_bytes_element_reader_unittest.cc b/chromium/net/base/upload_bytes_element_reader_unittest.cc index 1aad55ee5ce..1d2f52ffb2c 100644 --- a/chromium/net/base/upload_bytes_element_reader_unittest.cc +++ b/chromium/net/base/upload_bytes_element_reader_unittest.cc @@ -15,7 +15,7 @@ namespace net { class UploadBytesElementReaderTest : public PlatformTest { protected: - virtual void SetUp() OVERRIDE { + void SetUp() override { const char kData[] = "123abc"; bytes_.assign(kData, kData + arraysize(kData)); reader_.reset(new UploadBytesElementReader(&bytes_[0], bytes_.size())); diff --git a/chromium/net/base/upload_data_stream.cc b/chromium/net/base/upload_data_stream.cc index 785d5e936c7..936c9128833 100644 --- a/chromium/net/base/upload_data_stream.cc +++ b/chromium/net/base/upload_data_stream.cc @@ -4,261 +4,125 @@ #include "net/base/upload_data_stream.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_element_reader.h" namespace net { -UploadDataStream::UploadDataStream( - ScopedVector<UploadElementReader> element_readers, - int64 identifier) - : element_readers_(element_readers.Pass()), - element_index_(0), - total_size_(0), +UploadDataStream::UploadDataStream(bool is_chunked, int64 identifier) + : total_size_(0), current_position_(0), identifier_(identifier), - is_chunked_(false), - last_chunk_appended_(false), - read_failed_(false), + is_chunked_(is_chunked), initialized_successfully_(false), - weak_ptr_factory_(this) { -} - -UploadDataStream::UploadDataStream(Chunked /*chunked*/, int64 identifier) - : element_index_(0), - total_size_(0), - current_position_(0), - identifier_(identifier), - is_chunked_(true), - last_chunk_appended_(false), - read_failed_(false), - initialized_successfully_(false), - weak_ptr_factory_(this) { + is_eof_(false) { } UploadDataStream::~UploadDataStream() { } -UploadDataStream* UploadDataStream::CreateWithReader( - scoped_ptr<UploadElementReader> reader, - int64 identifier) { - ScopedVector<UploadElementReader> readers; - readers.push_back(reader.release()); - return new UploadDataStream(readers.Pass(), identifier); -} - int UploadDataStream::Init(const CompletionCallback& callback) { Reset(); - return InitInternal(0, callback); + DCHECK(!initialized_successfully_); + DCHECK(callback_.is_null()); + DCHECK(!callback.is_null() || IsInMemory()); + int result = InitInternal(); + if (result == ERR_IO_PENDING) { + DCHECK(!IsInMemory()); + callback_ = callback; + } else { + OnInitCompleted(result); + } + return result; } int UploadDataStream::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { + DCHECK(!callback.is_null() || IsInMemory()); DCHECK(initialized_successfully_); DCHECK_GT(buf_len, 0); - return ReadInternal(new DrainableIOBuffer(buf, buf_len), callback); + if (is_eof_) + return 0; + int result = ReadInternal(buf, buf_len); + if (result == ERR_IO_PENDING) { + DCHECK(!IsInMemory()); + callback_ = callback; + } else { + OnReadCompleted(result); + } + return result; } bool UploadDataStream::IsEOF() const { DCHECK(initialized_successfully_); - if (!is_chunked_) - return current_position_ == total_size_; - - // If the upload data is chunked, check if the last chunk is appended and all - // elements are consumed. - return element_index_ == element_readers_.size() && last_chunk_appended_; -} - -bool UploadDataStream::IsInMemory() const { - // Chunks are in memory, but UploadData does not have all the chunks at - // once. Chunks are provided progressively with AppendChunk() as chunks - // are ready. Check is_chunked_ here, rather than relying on the loop - // below, as there is a case that is_chunked_ is set to true, but the - // first chunk is not yet delivered. - if (is_chunked_) - return false; - - for (size_t i = 0; i < element_readers_.size(); ++i) { - if (!element_readers_[i]->IsInMemory()) - return false; - } - return true; -} - -void UploadDataStream::AppendChunk(const char* bytes, - int bytes_len, - bool is_last_chunk) { - DCHECK(is_chunked_); - DCHECK(!last_chunk_appended_); - last_chunk_appended_ = is_last_chunk; - - // Initialize a reader for the newly appended chunk. We leave |total_size_| at - // zero, since for chunked uploads, we may not know the total size. - std::vector<char> data(bytes, bytes + bytes_len); - UploadElementReader* reader = new UploadOwnedBytesElementReader(&data); - const int rv = reader->Init(net::CompletionCallback()); - DCHECK_EQ(OK, rv); - element_readers_.push_back(reader); - - // Resume pending read. - if (!pending_chunked_read_callback_.is_null()) { - base::Closure callback = pending_chunked_read_callback_; - pending_chunked_read_callback_.Reset(); - callback.Run(); - } + DCHECK(is_chunked_ || is_eof_ == (current_position_ == total_size_)); + return is_eof_; } void UploadDataStream::Reset() { - weak_ptr_factory_.InvalidateWeakPtrs(); - pending_chunked_read_callback_.Reset(); - initialized_successfully_ = false; - read_failed_ = false; current_position_ = 0; + initialized_successfully_ = false; + is_eof_ = false; total_size_ = 0; - element_index_ = 0; + callback_.Reset(); + ResetInternal(); } -int UploadDataStream::InitInternal(int start_index, - const CompletionCallback& callback) { +void UploadDataStream::SetSize(uint64 size) { DCHECK(!initialized_successfully_); + DCHECK(!is_chunked_); + total_size_ = size; +} - // Call Init() for all elements. - for (size_t i = start_index; i < element_readers_.size(); ++i) { - UploadElementReader* reader = element_readers_[i]; - // When new_result is ERR_IO_PENDING, InitInternal() will be called - // with start_index == i + 1 when reader->Init() finishes. - const int result = reader->Init( - base::Bind(&UploadDataStream::ResumePendingInit, - weak_ptr_factory_.GetWeakPtr(), - i + 1, - callback)); - if (result != OK) { - DCHECK(result != ERR_IO_PENDING || !callback.is_null()); - return result; - } - } +void UploadDataStream::SetIsFinalChunk() { + DCHECK(initialized_successfully_); + DCHECK(is_chunked_); + DCHECK(!is_eof_); + is_eof_ = true; +} - // Finalize initialization. - if (!is_chunked_) { - uint64 total_size = 0; - for (size_t i = 0; i < element_readers_.size(); ++i) { - UploadElementReader* reader = element_readers_[i]; - total_size += reader->GetContentLength(); - } - total_size_ = total_size; - } - initialized_successfully_ = true; - return OK; +bool UploadDataStream::IsInMemory() const { + return false; +} + +const ScopedVector<UploadElementReader>* +UploadDataStream::GetElementReaders() const { + return NULL; } -void UploadDataStream::ResumePendingInit(int start_index, - const CompletionCallback& callback, - int previous_result) { +void UploadDataStream::OnInitCompleted(int result) { + DCHECK_NE(ERR_IO_PENDING, result); DCHECK(!initialized_successfully_); - DCHECK(!callback.is_null()); - DCHECK_NE(ERR_IO_PENDING, previous_result); + DCHECK_EQ(0u, current_position_); + DCHECK(!is_eof_); - // Check the last result. - if (previous_result != OK) { - callback.Run(previous_result); - return; + if (result == OK) { + initialized_successfully_ = true; + if (!is_chunked_ && total_size_ == 0) + is_eof_ = true; } - - const int result = InitInternal(start_index, callback); - if (result != ERR_IO_PENDING) - callback.Run(result); + if (!callback_.is_null()) + base::ResetAndReturn(&callback_).Run(result); } -int UploadDataStream::ReadInternal(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback) { +void UploadDataStream::OnReadCompleted(int result) { + DCHECK_GE(result, 0); DCHECK(initialized_successfully_); - while (!read_failed_ && element_index_ < element_readers_.size()) { - UploadElementReader* reader = element_readers_[element_index_]; - - if (reader->BytesRemaining() == 0) { - ++element_index_; - continue; - } - - if (buf->BytesRemaining() == 0) - break; - - int result = reader->Read( - buf.get(), - buf->BytesRemaining(), - base::Bind(base::IgnoreResult(&UploadDataStream::ResumePendingRead), - weak_ptr_factory_.GetWeakPtr(), - buf, - callback)); - if (result == ERR_IO_PENDING) { - DCHECK(!callback.is_null()); - return ERR_IO_PENDING; - } - ProcessReadResult(buf, result); - } - - if (read_failed_) { - // Chunked transfers may only contain byte readers, so cannot have read - // failures. - DCHECK(!is_chunked_); - - // If an error occured during read operation, then pad with zero. - // Otherwise the server will hang waiting for the rest of the data. - const int num_bytes_to_fill = - std::min(static_cast<uint64>(buf->BytesRemaining()), - size() - position() - buf->BytesConsumed()); - DCHECK_LE(0, num_bytes_to_fill); - memset(buf->data(), 0, num_bytes_to_fill); - buf->DidConsume(num_bytes_to_fill); - } - - const int bytes_copied = buf->BytesConsumed(); - current_position_ += bytes_copied; - DCHECK(is_chunked_ || total_size_ >= current_position_); - - if (is_chunked_ && !IsEOF() && bytes_copied == 0) { - DCHECK(!callback.is_null()); - DCHECK(pending_chunked_read_callback_.is_null()); - pending_chunked_read_callback_ = - base::Bind(&UploadDataStream::ResumePendingRead, - weak_ptr_factory_.GetWeakPtr(), - buf, - callback, - OK); - return ERR_IO_PENDING; + current_position_ += result; + if (!is_chunked_) { + DCHECK_LE(current_position_, total_size_); + if (current_position_ == total_size_) + is_eof_ = true; } - // Returning 0 is allowed only when IsEOF() == true. - DCHECK(bytes_copied != 0 || IsEOF()); - return bytes_copied; -} - -void UploadDataStream::ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback, - int previous_result) { - DCHECK(!callback.is_null()); - - ProcessReadResult(buf, previous_result); - - const int result = ReadInternal(buf, callback); - if (result != ERR_IO_PENDING) - callback.Run(result); -} - -void UploadDataStream::ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, - int result) { - DCHECK_NE(ERR_IO_PENDING, result); - DCHECK(!read_failed_); + DCHECK(result > 0 || is_eof_); - if (result >= 0) - buf->DidConsume(result); - else - read_failed_ = true; + if (!callback_.is_null()) + base::ResetAndReturn(&callback_).Run(result); } } // namespace net diff --git a/chromium/net/base/upload_data_stream.h b/chromium/net/base/upload_data_stream.h index ac14e38086f..d7df8c9ae44 100644 --- a/chromium/net/base/upload_data_stream.h +++ b/chromium/net/base/upload_data_stream.h @@ -5,10 +5,9 @@ #ifndef NET_BASE_UPLOAD_DATA_STREAM_H_ #define NET_BASE_UPLOAD_DATA_STREAM_H_ -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" +#include "base/basictypes.h" +#include "base/macros.h" #include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" @@ -18,31 +17,22 @@ class DrainableIOBuffer; class IOBuffer; class UploadElementReader; -// A class to read all elements from an UploadData object. +// A class for retrieving all data to be sent as a request body. Supports both +// chunked and non-chunked uploads. class NET_EXPORT UploadDataStream { public: - // An enum used to construct chunked data stream. - enum Chunked { CHUNKED }; + // |identifier| identifies a particular upload instance, which is used by the + // cache to formulate a cache key. This value should be unique across browser + // sessions. A value of 0 is used to indicate an unspecified identifier. + UploadDataStream(bool is_chunked, int64 identifier); - // Constructs a non-chunked data stream. - UploadDataStream(ScopedVector<UploadElementReader> element_readers, - int64 identifier); - - // Constructs a chunked data stream. - UploadDataStream(Chunked chunked, int64 identifier); - - ~UploadDataStream(); - - // Creates UploadDataStream with a reader. - static UploadDataStream* CreateWithReader( - scoped_ptr<UploadElementReader> reader, - int64 identifier); + virtual ~UploadDataStream(); // Initializes the stream. This function must be called before calling any // other method. It is not valid to call any method (other than the - // destructor) if Init() returns a failure. This method can be called multiple - // times. Calling this method after a Init() success results in resetting the - // state. + // destructor) if Init() fails. This method can be called multiple times. + // Calling this method after an Init() success results in resetting the + // state (i.e. the stream is rewound). // // Does the initialization synchronously and returns the result if possible, // otherwise returns ERR_IO_PENDING and runs the callback with the result. @@ -62,93 +52,88 @@ class NET_EXPORT UploadDataStream { // If there's less data to read than we initially observed (i.e. the actual // upload data is smaller than size()), zeros are padded to ensure that // size() bytes can be read, which can happen for TYPE_FILE payloads. + // + // Reads are currently not allowed to fail - they must either return + // a value >= 0 or ERR_IO_PENDING, and call OnReadCompleted with a + // value >= 0. + // TODO(mmenke): Investigate letting reads fail. int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback); - // Identifies a particular upload instance, which is used by the cache to - // formulate a cache key. This value should be unique across browser - // sessions. A value of 0 is used to indicate an unspecified identifier. - int64 identifier() const { return identifier_; } - // Returns the total size of the data stream and the current position. - // size() is not to be used to determine whether the stream has ended - // because it is possible for the stream to end before its size is reached, - // for example, if the file is truncated. When the data is chunked, size() - // always returns zero. + // When the data is chunked, always returns zero. Must always return the same + // value after each call to Initialize(). uint64 size() const { return total_size_; } uint64 position() const { return current_position_; } - bool is_chunked() const { return is_chunked_; } - bool last_chunk_appended() const { return last_chunk_appended_; } + // See constructor for description. + int64 identifier() const { return identifier_; } - const ScopedVector<UploadElementReader>& element_readers() const { - return element_readers_; - } + bool is_chunked() const { return is_chunked_; } // Returns true if all data has been consumed from this upload data - // stream. + // stream. For chunked uploads, returns false until the first read attempt. + // This makes some state machines a little simpler. bool IsEOF() const; - // Returns true if the upload data in the stream is entirely in memory. - bool IsInMemory() const; + // Cancels all pending callbacks, and resets state. Any IOBuffer currently + // being read to is not safe for future use, as it may be in use on another + // thread. + void Reset(); + + // Returns true if the upload data in the stream is entirely in memory, and + // all read requests will succeed synchronously. Expected to return false for + // chunked requests. + virtual bool IsInMemory() const; - // Adds the given chunk of bytes to be sent with chunked transfer encoding. - void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); + // Returns a list of element readers owned by |this|, if it has any. + virtual const ScopedVector<UploadElementReader>* + GetElementReaders() const; - // Resets this instance to the uninitialized state. - void Reset(); + protected: + // Must be called by subclasses when InitInternal and ReadInternal complete + // asynchronously. + void OnInitCompleted(int result); + void OnReadCompleted(int result); + + // Must be called before InitInternal completes, for non-chunked uploads. + // Must not be called for chunked uploads. + void SetSize(uint64 size); + + // Must be called for chunked uploads before the final ReadInternal call + // completes. Must not be called for non-chunked uploads. + void SetIsFinalChunk(); private: - // Runs Init() for all element readers. - // This method is used to implement Init(). - int InitInternal(int start_index, const CompletionCallback& callback); - - // Resumes initialization and runs callback with the result when necessary. - void ResumePendingInit(int start_index, - const CompletionCallback& callback, - int previous_result); - - // Reads data from the element readers. - // This method is used to implement Read(). - int ReadInternal(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback); - - // Resumes pending read and calls callback with the result when necessary. - void ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback, - int previous_result); - - // Processes result of UploadElementReader::Read(). If |result| indicates - // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. - void ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, - int result); - - ScopedVector<UploadElementReader> element_readers_; - - // Index of the current upload element (i.e. the element currently being - // read). The index is used as a cursor to iterate over elements in - // |upload_data_|. - size_t element_index_; - - // Size and current read position within the upload data stream. - // |total_size_| is set to zero when the data is chunked. + // See Init(). If it returns ERR_IO_PENDING, OnInitCompleted must be called + // once it completes. If the upload is not chunked, SetSize must be called + // before it completes. + virtual int InitInternal() = 0; + + // See Read(). For chunked uploads, must call SetIsFinalChunk if this is the + // final chunk. For non-chunked uploads, the UploadDataStream determins which + // read is the last based on size. Must read 1 or more bytes on every call, + // though the final chunk may be 0 bytes, for chunked requests. If it returns + // ERR_IO_PENDING, OnInitCompleted must be called once it completes. Must not + // return any error, other than ERR_IO_PENDING. + virtual int ReadInternal(IOBuffer* buf, int buf_len) = 0; + + // Resets state and cancels any pending callbacks. Guaranteed to be called + // before all but the first call to InitInternal. + virtual void ResetInternal() = 0; + uint64 total_size_; uint64 current_position_; const int64 identifier_; const bool is_chunked_; - bool last_chunk_appended_; - - // True if an error occcured during read operation. - bool read_failed_; // True if the initialization was successful. bool initialized_successfully_; - // Callback to resume reading chunked data. - base::Closure pending_chunked_read_callback_; + bool is_eof_; - base::WeakPtrFactory<UploadDataStream> weak_ptr_factory_; + CompletionCallback callback_; DISALLOW_COPY_AND_ASSIGN(UploadDataStream); }; diff --git a/chromium/net/base/upload_element.cc b/chromium/net/base/upload_element.cc deleted file mode 100644 index 6b6438aec26..00000000000 --- a/chromium/net/base/upload_element.cc +++ /dev/null @@ -1,25 +0,0 @@ -// 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 "net/base/upload_element.h" - -#include <algorithm> - -#include "net/base/file_stream.h" -#include "net/base/net_errors.h" - -namespace net { - -UploadElement::UploadElement() - : type_(TYPE_BYTES), - bytes_start_(NULL), - bytes_length_(0), - file_range_offset_(0), - file_range_length_(kuint64max) { -} - -UploadElement::~UploadElement() { -} - -} // namespace net diff --git a/chromium/net/base/upload_element.h b/chromium/net/base/upload_element.h deleted file mode 100644 index 34f601464d9..00000000000 --- a/chromium/net/base/upload_element.h +++ /dev/null @@ -1,110 +0,0 @@ -// 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 NET_BASE_UPLOAD_ELEMENT_H_ -#define NET_BASE_UPLOAD_ELEMENT_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/time/time.h" -#include "net/base/net_export.h" - -namespace net { - -// A class representing an element contained by UploadData. -class NET_EXPORT UploadElement { - public: - enum Type { - TYPE_BYTES, - TYPE_FILE, - }; - - UploadElement(); - ~UploadElement(); - - Type type() const { return type_; } - - const char* bytes() const { return bytes_start_ ? bytes_start_ : &buf_[0]; } - uint64 bytes_length() const { return buf_.size() + bytes_length_; } - const base::FilePath& file_path() const { return file_path_; } - uint64 file_range_offset() const { return file_range_offset_; } - uint64 file_range_length() const { return file_range_length_; } - // If NULL time is returned, we do not do the check. - const base::Time& expected_file_modification_time() const { - return expected_file_modification_time_; - } - - void SetToBytes(const char* bytes, int bytes_len) { - type_ = TYPE_BYTES; - buf_.assign(bytes, bytes + bytes_len); - } - - // This does not copy the given data and the caller should make sure - // the data is secured somewhere else (e.g. by attaching the data - // using SetUserData). - void SetToSharedBytes(const char* bytes, int bytes_len) { - type_ = TYPE_BYTES; - bytes_start_ = bytes; - bytes_length_ = bytes_len; - } - - void SetToFilePath(const base::FilePath& path) { - SetToFilePathRange(path, 0, kuint64max, base::Time()); - } - - // If expected_modification_time is NULL, we do not check for the file - // change. Also note that the granularity for comparison is time_t, not - // the full precision. - void SetToFilePathRange(const base::FilePath& path, - uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - type_ = TYPE_FILE; - file_path_ = path; - file_range_offset_ = offset; - file_range_length_ = length; - expected_file_modification_time_ = expected_modification_time; - } - - private: - Type type_; - std::vector<char> buf_; - const char* bytes_start_; - uint64 bytes_length_; - base::FilePath file_path_; - uint64 file_range_offset_; - uint64 file_range_length_; - base::Time expected_file_modification_time_; - - DISALLOW_COPY_AND_ASSIGN(UploadElement); -}; - -#if defined(UNIT_TEST) -inline bool operator==(const UploadElement& a, - const UploadElement& b) { - if (a.type() != b.type()) - return false; - if (a.type() == UploadElement::TYPE_BYTES) - return a.bytes_length() == b.bytes_length() && - memcmp(a.bytes(), b.bytes(), b.bytes_length()) == 0; - if (a.type() == UploadElement::TYPE_FILE) { - return a.file_path() == b.file_path() && - a.file_range_offset() == b.file_range_offset() && - a.file_range_length() == b.file_range_length() && - a.expected_file_modification_time() == - b.expected_file_modification_time(); - } - return false; -} - -inline bool operator!=(const UploadElement& a, - const UploadElement& b) { - return !(a == b); -} -#endif // defined(UNIT_TEST) - -} // namespace net - -#endif // NET_BASE_UPLOAD_ELEMENT_H_ diff --git a/chromium/net/base/upload_element_reader.h b/chromium/net/base/upload_element_reader.h index d71f57cdb64..a46b9709fa8 100644 --- a/chromium/net/base/upload_element_reader.h +++ b/chromium/net/base/upload_element_reader.h @@ -35,8 +35,8 @@ class NET_EXPORT UploadElementReader { // state. virtual int Init(const CompletionCallback& callback) = 0; - // Returns the byte-length of the element. For files that do not exist, 0 - // is returned. This is done for consistency with Mozilla. + // Returns the byte-length of the element. For files that do not exist, 0 + // is returned. This is done for consistency with Mozilla. virtual uint64 GetContentLength() const = 0; // Returns the number of bytes remaining to read. diff --git a/chromium/net/base/upload_file_element_reader.cc b/chromium/net/base/upload_file_element_reader.cc index f8775ee567b..46824668cce 100644 --- a/chromium/net/base/upload_file_element_reader.cc +++ b/chromium/net/base/upload_file_element_reader.cc @@ -5,8 +5,9 @@ #include "net/base/upload_file_element_reader.h" #include "base/bind.h" -#include "base/file_util.h" +#include "base/files/file_util.h" #include "base/location.h" +#include "base/profiler/scoped_tracker.h" #include "base/task_runner_util.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" @@ -103,6 +104,11 @@ void UploadFileElementReader::Reset() { void UploadFileElementReader::OnOpenCompleted( const CompletionCallback& callback, int result) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 UploadFileElementReader::OnOpenCompleted")); + DCHECK(!callback.is_null()); if (result < 0) { @@ -114,7 +120,7 @@ void UploadFileElementReader::OnOpenCompleted( if (range_offset_) { int result = file_stream_->Seek( - FROM_BEGIN, range_offset_, + base::File::FROM_BEGIN, range_offset_, base::Bind(&UploadFileElementReader::OnSeekCompleted, weak_ptr_factory_.GetWeakPtr(), callback)); @@ -140,11 +146,9 @@ void UploadFileElementReader::OnSeekCompleted( base::File::Info* file_info = new base::File::Info; bool posted = base::PostTaskAndReplyWithResult( - task_runner_, + task_runner_.get(), FROM_HERE, - base::Bind(&base::GetFileInfo, - path_, - file_info), + base::Bind(&base::GetFileInfo, path_, file_info), base::Bind(&UploadFileElementReader::OnGetFileInfoCompleted, weak_ptr_factory_.GetWeakPtr(), callback, diff --git a/chromium/net/base/upload_file_element_reader.h b/chromium/net/base/upload_file_element_reader.h index 12427174377..fc3f3349a8b 100644 --- a/chromium/net/base/upload_file_element_reader.h +++ b/chromium/net/base/upload_file_element_reader.h @@ -32,7 +32,7 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { uint64 range_offset, uint64 range_length, const base::Time& expected_modification_time); - virtual ~UploadFileElementReader(); + ~UploadFileElementReader() override; const base::FilePath& path() const { return path_; } uint64 range_offset() const { return range_offset_; } @@ -42,22 +42,18 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { } // UploadElementReader overrides: - virtual const UploadFileElementReader* AsFileReader() const OVERRIDE; - virtual int Init(const CompletionCallback& callback) OVERRIDE; - virtual uint64 GetContentLength() const OVERRIDE; - virtual uint64 BytesRemaining() const OVERRIDE; - virtual int Read(IOBuffer* buf, - int buf_length, - const CompletionCallback& callback) OVERRIDE; + const UploadFileElementReader* AsFileReader() const override; + int Init(const CompletionCallback& callback) override; + uint64 GetContentLength() const override; + uint64 BytesRemaining() const override; + int Read(IOBuffer* buf, + int buf_length, + const CompletionCallback& callback) override; private: - FRIEND_TEST_ALL_PREFIXES(UploadDataStreamTest, FileSmallerThanLength); + FRIEND_TEST_ALL_PREFIXES(ElementsUploadDataStreamTest, FileSmallerThanLength); FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, UploadFileSmallerThanLength); - FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionSpdy2Test, - UploadFileSmallerThanLength); - FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionSpdy3Test, - UploadFileSmallerThanLength); // Resets this instance to the uninitialized state. void Reset(); diff --git a/chromium/net/base/upload_file_element_reader_unittest.cc b/chromium/net/base/upload_file_element_reader_unittest.cc index 395b8673724..b0374acd966 100644 --- a/chromium/net/base/upload_file_element_reader_unittest.cc +++ b/chromium/net/base/upload_file_element_reader_unittest.cc @@ -4,7 +4,7 @@ #include "net/base/upload_file_element_reader.h" -#include "base/file_util.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/message_loop/message_loop_proxy.h" #include "base/run_loop.h" @@ -18,7 +18,7 @@ namespace net { class UploadFileElementReaderTest : public PlatformTest { protected: - virtual void SetUp() { + void SetUp() override { PlatformTest::SetUp(); // Some tests (*.ReadPartially) rely on bytes_.size() being even. const char kData[] = "123456789abcdefghi"; @@ -46,7 +46,7 @@ class UploadFileElementReaderTest : public PlatformTest { EXPECT_FALSE(reader_->IsInMemory()); } - virtual ~UploadFileElementReaderTest() { + ~UploadFileElementReaderTest() override { reader_.reset(); base::RunLoop().RunUntilIdle(); } |