OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // For loading files, we make use of overlapped i/o to ensure that reading from | 5 // For loading files, we make use of overlapped i/o to ensure that reading from |
6 // the filesystem (e.g., a network filesystem) does not block the calling | 6 // the filesystem (e.g., a network filesystem) does not block the calling |
7 // thread. An alternative approach would be to use a background thread or pool | 7 // thread. An alternative approach would be to use a background thread or pool |
8 // of threads, but it seems better to leverage the operating system's ability | 8 // of threads, but it seems better to leverage the operating system's ability |
9 // to do background file reads for us. | 9 // to do background file reads for us. |
10 // | 10 // |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 | 65 |
66 Lock lock_; | 66 Lock lock_; |
67 MessageLoop* owner_loop_; | 67 MessageLoop* owner_loop_; |
68 }; | 68 }; |
69 #endif | 69 #endif |
70 | 70 |
71 // static | 71 // static |
72 URLRequestJob* URLRequestFileJob::Factory( | 72 URLRequestJob* URLRequestFileJob::Factory( |
73 URLRequest* request, const std::string& scheme) { | 73 URLRequest* request, const std::string& scheme) { |
74 FilePath file_path; | 74 FilePath file_path; |
75 if (net::FileURLToFilePath(request->url(), &file_path)) { | 75 if (net::FileURLToFilePath(request->url(), &file_path) && |
76 if (file_util::DirectoryExists(file_path)) { | 76 file_util::EnsureEndsWithSeparator(&file_path)) |
77 // Only directories have trailing slashes. | |
78 return new URLRequestFileDirJob(request, file_path); | 77 return new URLRequestFileDirJob(request, file_path); |
79 } | |
80 } | |
81 | 78 |
82 // Use a regular file request job for all non-directories (including invalid | 79 // Use a regular file request job for all non-directories (including invalid |
83 // file names). | 80 // file names). |
84 URLRequestFileJob* job = new URLRequestFileJob(request); | 81 URLRequestFileJob* job = new URLRequestFileJob(request); |
85 job->file_path_ = file_path; | 82 job->file_path_ = file_path; |
86 return job; | 83 return job; |
87 } | 84 } |
88 | 85 |
89 URLRequestFileJob::URLRequestFileJob(URLRequest* request) | 86 URLRequestFileJob::URLRequestFileJob(URLRequest* request) |
90 : URLRequestJob(request), | 87 : URLRequestJob(request), |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 void URLRequestFileJob::DidResolve( | 157 void URLRequestFileJob::DidResolve( |
161 bool exists, const file_util::FileInfo& file_info) { | 158 bool exists, const file_util::FileInfo& file_info) { |
162 #if defined(OS_WIN) | 159 #if defined(OS_WIN) |
163 async_resolver_ = NULL; | 160 async_resolver_ = NULL; |
164 #endif | 161 #endif |
165 | 162 |
166 // We may have been orphaned... | 163 // We may have been orphaned... |
167 if (!request_) | 164 if (!request_) |
168 return; | 165 return; |
169 | 166 |
170 is_directory_ = file_info.is_directory; | 167 DCHECK(!file_info.is_directory); |
171 | 168 |
172 int rv = net::OK; | 169 int rv = net::OK; |
173 if (!exists) { | 170 if (!exists) { |
174 rv = net::ERR_FILE_NOT_FOUND; | 171 rv = net::ERR_FILE_NOT_FOUND; |
175 } else if (!is_directory_) { | 172 } else { |
176 int flags = base::PLATFORM_FILE_OPEN | | 173 int flags = base::PLATFORM_FILE_OPEN | |
177 base::PLATFORM_FILE_READ | | 174 base::PLATFORM_FILE_READ | |
178 base::PLATFORM_FILE_ASYNC; | 175 base::PLATFORM_FILE_ASYNC; |
179 rv = stream_.Open(file_path_.ToWStringHack(), flags); | 176 rv = stream_.Open(file_path_.ToWStringHack(), flags); |
180 } | 177 } |
181 | 178 |
182 if (rv == net::OK) { | 179 if (rv == net::OK) { |
183 set_expected_content_size(file_info.size); | 180 set_expected_content_size(file_info.size); |
184 NotifyHeadersComplete(); | 181 NotifyHeadersComplete(); |
185 } else { | 182 } else { |
186 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); | 183 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
187 } | 184 } |
188 } | 185 } |
189 | 186 |
190 void URLRequestFileJob::DidRead(int result) { | 187 void URLRequestFileJob::DidRead(int result) { |
191 if (result > 0) { | 188 if (result > 0) { |
192 SetStatus(URLRequestStatus()); // Clear the IO_PENDING status | 189 SetStatus(URLRequestStatus()); // Clear the IO_PENDING status |
193 } else if (result == 0) { | 190 } else if (result == 0) { |
194 NotifyDone(URLRequestStatus()); | 191 NotifyDone(URLRequestStatus()); |
195 } else { | 192 } else { |
196 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); | 193 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); |
197 } | 194 } |
198 NotifyReadComplete(result); | 195 NotifyReadComplete(result); |
199 } | 196 } |
200 | 197 |
201 bool URLRequestFileJob::IsRedirectResponse( | 198 bool URLRequestFileJob::IsRedirectResponse( |
202 GURL* location, int* http_status_code) { | 199 GURL* location, int* http_status_code) { |
203 if (is_directory_) { | |
204 // This happens when we discovered the file is a directory, so needs a | |
205 // slash at the end of the path. | |
206 std::string new_path = request_->url().path(); | |
207 new_path.push_back('/'); | |
208 GURL::Replacements replacements; | |
209 replacements.SetPathStr(new_path); | |
210 | |
211 *location = request_->url().ReplaceComponents(replacements); | |
212 *http_status_code = 301; // simulate a permanent redirect | |
213 return true; | |
214 } | |
215 | |
216 #if defined(OS_WIN) | 200 #if defined(OS_WIN) |
217 std::wstring extension = | 201 std::wstring extension = |
218 file_util::GetFileExtensionFromPath(file_path_.value()); | 202 file_util::GetFileExtensionFromPath(file_path_.value()); |
219 | 203 |
220 // Follow a Windows shortcut. | 204 // Follow a Windows shortcut. |
221 // We just resolve .lnk file, ignore others. | 205 // We just resolve .lnk file, ignore others. |
222 if (!LowerCaseEqualsASCII(extension, "lnk")) | 206 if (!LowerCaseEqualsASCII(extension, "lnk")) |
223 return false; | 207 return false; |
224 | 208 |
225 std::wstring new_path = file_path_.value(); | 209 std::wstring new_path = file_path_.value(); |
226 bool resolved; | 210 bool resolved; |
227 resolved = file_util::ResolveShortcut(&new_path); | 211 resolved = file_util::ResolveShortcut(&new_path); |
228 | 212 |
229 // If shortcut is not resolved succesfully, do not redirect. | 213 // If shortcut is not resolved succesfully, do not redirect. |
230 if (!resolved) | 214 if (!resolved) |
231 return false; | 215 return false; |
232 | 216 |
233 *location = net::FilePathToFileURL(new_path); | 217 *location = net::FilePathToFileURL(new_path); |
234 *http_status_code = 301; | 218 *http_status_code = 301; |
235 return true; | 219 return true; |
236 #else | 220 #else |
237 return false; | 221 return false; |
238 #endif | 222 #endif |
239 } | 223 } |
240 | 224 |
OLD | NEW |