Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / net / url_request / url_request_file_job_unittest.cc
blobaf05259c780cb89d28dfc720c4a7b1ef2ce2f5e2
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/url_request/url_request_file_job.h"
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "net/base/filename_util.h"
14 #include "net/base/net_util.h"
15 #include "net/url_request/url_request.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace net {
21 namespace {
23 // A URLRequestFileJob for testing OnSeekComplete / OnReadComplete callbacks.
24 class URLRequestFileJobWithCallbacks : public URLRequestFileJob {
25 public:
26 URLRequestFileJobWithCallbacks(
27 URLRequest* request,
28 NetworkDelegate* network_delegate,
29 const base::FilePath& file_path,
30 const scoped_refptr<base::TaskRunner>& file_task_runner)
31 : URLRequestFileJob(request,
32 network_delegate,
33 file_path,
34 file_task_runner),
35 seek_position_(0) {
38 int64 seek_position() { return seek_position_; }
39 const std::vector<std::string>& data_chunks() { return data_chunks_; }
41 protected:
42 ~URLRequestFileJobWithCallbacks() override {}
44 void OnSeekComplete(int64 result) override {
45 ASSERT_EQ(seek_position_, 0);
46 seek_position_ = result;
49 void OnReadComplete(IOBuffer* buf, int result) override {
50 data_chunks_.push_back(std::string(buf->data(), result));
53 int64 seek_position_;
54 std::vector<std::string> data_chunks_;
57 // A URLRequestJobFactory that will return URLRequestFileJobWithCallbacks
58 // instances for file:// scheme URLs.
59 class CallbacksJobFactory : public URLRequestJobFactory {
60 public:
61 class JobObserver {
62 public:
63 virtual void OnJobCreated(URLRequestFileJobWithCallbacks* job) = 0;
66 CallbacksJobFactory(const base::FilePath& path, JobObserver* observer)
67 : path_(path), observer_(observer) {
70 ~CallbacksJobFactory() override {}
72 URLRequestJob* MaybeCreateJobWithProtocolHandler(
73 const std::string& scheme,
74 URLRequest* request,
75 NetworkDelegate* network_delegate) const override {
76 URLRequestFileJobWithCallbacks* job = new URLRequestFileJobWithCallbacks(
77 request,
78 network_delegate,
79 path_,
80 base::MessageLoop::current()->message_loop_proxy());
81 observer_->OnJobCreated(job);
82 return job;
85 net::URLRequestJob* MaybeInterceptRedirect(
86 net::URLRequest* request,
87 net::NetworkDelegate* network_delegate,
88 const GURL& location) const override {
89 return nullptr;
92 net::URLRequestJob* MaybeInterceptResponse(
93 net::URLRequest* request,
94 net::NetworkDelegate* network_delegate) const override {
95 return nullptr;
98 bool IsHandledProtocol(const std::string& scheme) const override {
99 return scheme == "file";
102 bool IsHandledURL(const GURL& url) const override {
103 return IsHandledProtocol(url.scheme());
106 bool IsSafeRedirectTarget(const GURL& location) const override {
107 return false;
110 private:
111 base::FilePath path_;
112 JobObserver* observer_;
115 // Helper function to create a file in |directory| filled with
116 // |content|. Returns true on succes and fills in |path| with the full path to
117 // the file.
118 bool CreateTempFileWithContent(const std::string& content,
119 const base::ScopedTempDir& directory,
120 base::FilePath* path) {
121 if (!directory.IsValid())
122 return false;
124 if (!base::CreateTemporaryFileInDir(directory.path(), path))
125 return false;
127 return base::WriteFile(*path, content.c_str(), content.length());
130 class JobObserverImpl : public CallbacksJobFactory::JobObserver {
131 public:
132 void OnJobCreated(URLRequestFileJobWithCallbacks* job) override {
133 jobs_.push_back(job);
136 typedef std::vector<scoped_refptr<URLRequestFileJobWithCallbacks> > JobList;
138 const JobList& jobs() { return jobs_; }
140 protected:
141 JobList jobs_;
144 // A simple holder for start/end used in http range requests.
145 struct Range {
146 int start;
147 int end;
149 Range() {
150 start = 0;
151 end = 0;
154 Range(int start, int end) {
155 this->start = start;
156 this->end = end;
160 // A superclass for tests of the OnSeekComplete / OnReadComplete functions of
161 // URLRequestFileJob.
162 class URLRequestFileJobEventsTest : public testing::Test {
163 public:
164 URLRequestFileJobEventsTest();
166 protected:
167 // This creates a file with |content| as the contents, and then creates and
168 // runs a URLRequestFileJobWithCallbacks job to get the contents out of it,
169 // and makes sure that the callbacks observed the correct bytes. If a Range
170 // is provided, this function will add the appropriate Range http header to
171 // the request and verify that only the bytes in that range (inclusive) were
172 // observed.
173 void RunRequest(const std::string& content, const Range* range);
175 JobObserverImpl observer_;
176 TestURLRequestContext context_;
177 TestDelegate delegate_;
180 URLRequestFileJobEventsTest::URLRequestFileJobEventsTest() {}
182 void URLRequestFileJobEventsTest::RunRequest(const std::string& content,
183 const Range* range) {
184 base::ScopedTempDir directory;
185 ASSERT_TRUE(directory.CreateUniqueTempDir());
186 base::FilePath path;
187 ASSERT_TRUE(CreateTempFileWithContent(content, directory, &path));
188 CallbacksJobFactory factory(path, &observer_);
189 context_.set_job_factory(&factory);
191 scoped_ptr<URLRequest> request(context_.CreateRequest(
192 FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_));
193 if (range) {
194 ASSERT_GE(range->start, 0);
195 ASSERT_GE(range->end, 0);
196 ASSERT_LE(range->start, range->end);
197 ASSERT_LT(static_cast<unsigned int>(range->end), content.length());
198 std::string range_value =
199 base::StringPrintf("bytes=%d-%d", range->start, range->end);
200 request->SetExtraRequestHeaderByName(
201 HttpRequestHeaders::kRange, range_value, true /*overwrite*/);
203 request->Start();
205 base::RunLoop loop;
206 loop.Run();
208 EXPECT_FALSE(delegate_.request_failed());
209 int expected_length =
210 range ? (range->end - range->start + 1) : content.length();
211 EXPECT_EQ(delegate_.bytes_received(), expected_length);
213 std::string expected_content;
214 if (range) {
215 expected_content.insert(0, content, range->start, expected_length);
216 } else {
217 expected_content = content;
219 EXPECT_TRUE(delegate_.data_received() == expected_content);
221 ASSERT_EQ(observer_.jobs().size(), 1u);
222 ASSERT_EQ(observer_.jobs().at(0)->seek_position(), range ? range->start : 0);
224 std::string observed_content;
225 const std::vector<std::string>& chunks =
226 observer_.jobs().at(0)->data_chunks();
227 for (std::vector<std::string>::const_iterator i = chunks.begin();
228 i != chunks.end();
229 ++i) {
230 observed_content.append(*i);
232 EXPECT_EQ(expected_content, observed_content);
235 // Helper function to make a character array filled with |size| bytes of
236 // test content.
237 std::string MakeContentOfSize(int size) {
238 EXPECT_GE(size, 0);
239 std::string result;
240 result.reserve(size);
241 for (int i = 0; i < size; i++) {
242 result.append(1, static_cast<char>(i % 256));
244 return result;
247 TEST_F(URLRequestFileJobEventsTest, TinyFile) {
248 RunRequest(std::string("hello world"), NULL);
251 TEST_F(URLRequestFileJobEventsTest, SmallFile) {
252 RunRequest(MakeContentOfSize(17 * 1024), NULL);
255 TEST_F(URLRequestFileJobEventsTest, BigFile) {
256 RunRequest(MakeContentOfSize(3 * 1024 * 1024), NULL);
259 TEST_F(URLRequestFileJobEventsTest, Range) {
260 // Use a 15KB content file and read a range chosen somewhat arbitrarily but
261 // not aligned on any likely page boundaries.
262 int size = 15 * 1024;
263 Range range(1701, (6 * 1024) + 3);
264 RunRequest(MakeContentOfSize(size), &range);
267 } // namespace
269 } // namespace net