Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Unified Diff: chrome/browser/chromeos/drive/drive_url_request_job.cc

Issue 560313002: Use ExternalFileSystemBackend in the DriveURLRequestJob. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/drive/drive_url_request_job.cc
diff --git a/chrome/browser/chromeos/drive/drive_url_request_job.cc b/chrome/browser/chromeos/drive/drive_url_request_job.cc
index 2e1ebb123a0b238ae43517717b4f88577450556b..aeb89f9d6d4105900fb10b2bf0ad7c41fe1a7f1b 100644
--- a/chrome/browser/chromeos/drive/drive_url_request_job.cc
+++ b/chrome/browser/chromeos/drive/drive_url_request_job.cc
@@ -4,16 +4,19 @@
#include "chrome/browser/chromeos/drive/drive_url_request_job.h"
-#include <string>
+#include <algorithm>
+#include <vector>
#include "base/bind.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/chromeos/drive/drive.pb.h"
-#include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
-#include "chrome/browser/chromeos/drive/file_system_interface.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/extensions/api/file_handlers/mime_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
#include "net/base/net_errors.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
@@ -21,39 +24,153 @@
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
using content::BrowserThread;
namespace drive {
namespace {
-struct MimeTypeReplacement {
- const char* original_type;
- const char* new_type;
-};
+const char kWrongMimeTypeForMHTML[] = "message/rfc822";
+const char kCorrectMimeTypeForMHTML[] = "multipart/related";
mtomasz 2014/09/19 06:33:45 I think it's not wrong. It's just another mime typ
hirono 2014/09/19 07:00:43 Done.
+
+// Check if the |url| points a valid location or not.
+bool IsValidURL(const storage::FileSystemURL& url) {
+ switch (url.type()) {
+ case storage::kFileSystemTypeDrive: {
+ const base::FilePath my_drive_path = util::GetDriveMyDriveRootPath();
+ const base::FilePath drive_other_path =
+ util::GetDriveGrandRootPath().Append(util::kDriveOtherDirName);
+ const base::FilePath url_drive_path =
+ util::ExtractDrivePathFromFileSystemUrl(url);
+ return my_drive_path == url_drive_path ||
+ my_drive_path.IsParent(url_drive_path) ||
+ drive_other_path.IsParent(url_drive_path);
+ }
+ default:
+ return false;
+ }
+}
-const MimeTypeReplacement kMimeTypeReplacements[] = {
- {"message/rfc822", "multipart/related"} // Fixes MHTML
-};
+// Helper for obtaining FileSystemContext, FileSystemURL, and mime type on the
+// UI thread.
+class URLHelper {
+ public:
+ // The scoped pointer to control lifetime of the instance itself. The pointer
+ // is passed to callback functions and binds the lifetime of the instance to
+ // the callback's lifetime.
+ typedef scoped_ptr<URLHelper> Lifetime;
+
+ URLHelper(void* profile_id,
+ const GURL& url,
+ const DriveURLRequestJob::HelperCallback& callback)
+ : profile_id_(profile_id), url_(url), callback_(callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ Lifetime lifetime(this);
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&URLHelper::RunOnUIThread,
+ base::Unretained(this),
+ base::Passed(&lifetime)));
+ }
+
+ private:
+ void RunOnUIThread(Lifetime lifetime) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ Profile* const profile = reinterpret_cast<Profile*>(profile_id_);
+ if (!g_browser_process->profile_manager()->IsValidProfile(profile)) {
+ ReplyResult(net::ERR_FAILED);
+ return;
+ }
+ content::StoragePartition* const storage =
+ content::BrowserContext::GetStoragePartitionForSite(profile, url_);
+ DCHECK(storage);
+
+ scoped_refptr<storage::FileSystemContext> context =
+ storage->GetFileSystemContext();
+ DCHECK(context.get());
+
+ // Obtain the absolute path in the file system.
+ base::FilePath path = drive::util::GetDriveMountPointPath(profile);
+ drive::util::GetDriveGrandRootPath().AppendRelativePath(
+ util::DriveURLToFilePath(url_), &path);
+
+ storage::ExternalFileSystemBackend* const backend =
+ context->external_backend();
+ DCHECK(backend);
+
+ // Obtain the virtual path.
+ base::FilePath virtual_path;
+ if (!backend->GetVirtualPath(path, &virtual_path)) {
+ ReplyResult(net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+
+ // Obtain the file system URL.
+ // TODO(hirono): After removing MHTML support, stop to use the special
+ // drive: scheme and use filesystem: URL directly. crbug.com/415455
+ file_system_url_ = context->CreateCrackedFileSystemURL(
+ GURL(std::string(chrome::kDriveScheme) + ":"),
+ storage::kFileSystemTypeExternal,
+ virtual_path);
+ if (!IsValidURL(file_system_url_)) {
+ ReplyResult(net::ERR_INVALID_URL);
+ return;
+ }
-std::string FixupMimeType(const std::string& type) {
- for (size_t i = 0; i < arraysize(kMimeTypeReplacements); i++) {
- if (type == kMimeTypeReplacements[i].original_type)
- return kMimeTypeReplacements[i].new_type;
+ file_system_context_ = context;
+
+ extensions::app_file_handler_util::GetMimeTypeForLocalPath(
+ profile,
+ file_system_url_.path(),
+ base::Bind(&URLHelper::OnGotMimeTypeOnUIThread,
+ base::Unretained(this),
+ base::Passed(&lifetime)));
}
- return type;
-}
+
+ void OnGotMimeTypeOnUIThread(Lifetime lifetime,
+ const std::string& mime_type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ mime_type_ = mime_type;
+
+ if (mime_type_ == kWrongMimeTypeForMHTML)
+ mime_type_ = kCorrectMimeTypeForMHTML;
+
+ ReplyResult(net::OK);
+ }
+
+ void ReplyResult(net::Error error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback_,
+ error,
+ file_system_context_,
+ file_system_url_,
+ mime_type_));
+ }
+
+ void* const profile_id_;
+ const GURL url_;
+ const DriveURLRequestJob::HelperCallback callback_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ storage::FileSystemURL file_system_url_;
+ std::string mime_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLHelper);
+};
} // namespace
-DriveURLRequestJob::DriveURLRequestJob(
- const FileSystemGetter& file_system_getter,
- base::SequencedTaskRunner* file_task_runner,
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate)
+DriveURLRequestJob::DriveURLRequestJob(void* profile_id,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
: net::URLRequestJob(request, network_delegate),
- file_system_getter_(file_system_getter),
- file_task_runner_(file_task_runner),
+ profile_id_(profile_id),
+ remaining_bytes_(0),
weak_ptr_factory_(this) {
}
@@ -77,7 +194,7 @@ void DriveURLRequestJob::SetExtraRequestHeaders(
void DriveURLRequestJob::Start() {
DVLOG(1) << "Starting request";
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!stream_reader_);
// We only support GET request.
@@ -89,54 +206,122 @@ void DriveURLRequestJob::Start() {
return;
}
- base::FilePath drive_file_path(util::DriveURLToFilePath(request_->url()));
- if (drive_file_path.empty()) {
- // Not a valid url.
+ // Check if the scheme is correct.
+ if (!request()->url().SchemeIs(chrome::kDriveScheme)) {
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
net::ERR_INVALID_URL));
return;
}
- // Initialize the stream reader.
- stream_reader_.reset(
- new DriveFileStreamReader(file_system_getter_, file_task_runner_.get()));
- stream_reader_->Initialize(
- drive_file_path,
- byte_range_,
- base::Bind(&DriveURLRequestJob::OnDriveFileStreamReaderInitialized,
+ // Owned by itself.
+ new URLHelper(profile_id_,
+ request()->url(),
+ base::Bind(&DriveURLRequestJob::OnHelperResultObtained,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DriveURLRequestJob::OnHelperResultObtained(
+ net::Error error,
+ const scoped_refptr<storage::FileSystemContext>& file_system_context,
+ const storage::FileSystemURL& file_system_url,
+ const std::string& mime_type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (error != net::OK) {
+ NotifyStartError(
+ net::URLRequestStatus(net::URLRequestStatus::FAILED, error));
+ return;
+ }
+
+ DCHECK(file_system_context.get());
+ file_system_context_ = file_system_context;
+ file_system_url_ = file_system_url;
+ mime_type_ = mime_type;
+
+ // Check if the entry has a redirect URL.
+ file_system_context_->external_backend()->GetRedirectURLForContents(
+ file_system_url_,
+ base::Bind(&DriveURLRequestJob::OnRedirectURLObtained,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DriveURLRequestJob::OnRedirectURLObtained(const GURL& redirect_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ redirect_url_ = redirect_url;
+ if (!redirect_url_.is_empty()) {
+ NotifyHeadersComplete();
+ return;
+ }
+
+ // Obtain file system context.
+ file_system_context_->operation_runner()->GetMetadata(
+ file_system_url_,
+ base::Bind(&DriveURLRequestJob::OnFileInfoObtained,
weak_ptr_factory_.GetWeakPtr()));
}
+void DriveURLRequestJob::OnFileInfoObtained(base::File::Error result,
+ const base::File::Info& file_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (result == base::File::FILE_ERROR_NOT_FOUND) {
+ NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FILE_NOT_FOUND));
+ return;
+ }
+
+ if (result != base::File::FILE_OK || file_info.is_directory) {
+ NotifyStartError(
+ net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
+ return;
+ }
+
+ // Compute content size.
+ int64 offset = 0;
+ int64 size = storage::kMaximumLength;
+ if (byte_range_.ComputeBounds(file_info.size)) {
+ offset = byte_range_.first_byte_position();
+ size = byte_range_.last_byte_position() + 1 -
+ byte_range_.first_byte_position();
+ set_expected_content_size(size);
+ }
+ remaining_bytes_ = size;
+
+ // Create file stream reader.
+ stream_reader_ = file_system_context_->CreateFileStreamReader(
+ file_system_url_, offset, size, base::Time());
+ if (!stream_reader_) {
+ NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FILE_NOT_FOUND));
+ return;
+ }
+
+ NotifyHeadersComplete();
+}
+
void DriveURLRequestJob::Kill() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
stream_reader_.reset();
+ file_system_context_ = NULL;
net::URLRequestJob::Kill();
weak_ptr_factory_.InvalidateWeakPtrs();
}
bool DriveURLRequestJob::GetMimeType(std::string* mime_type) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!entry_) {
- return false;
- }
-
- mime_type->assign(
- FixupMimeType(entry_->file_specific_info().content_mime_type()));
+ mime_type->assign(mime_type_);
return !mime_type->empty();
}
bool DriveURLRequestJob::IsRedirectResponse(
GURL* location, int* http_status_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!entry_ || !entry_->file_specific_info().is_hosted_document()) {
+ if (redirect_url_.is_empty())
return false;
- }
// Redirect a hosted document.
- *location = GURL(entry_->file_specific_info().alternate_url());
+ *location = redirect_url_;
const int kHttpFound = 302;
*http_status_code = kHttpFound;
return true;
@@ -145,10 +330,16 @@ bool DriveURLRequestJob::IsRedirectResponse(
bool DriveURLRequestJob::ReadRawData(
net::IOBuffer* buf, int buf_size, int* bytes_read) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(stream_reader_ && stream_reader_->IsInitialized());
+ DCHECK(stream_reader_);
+
+ if (remaining_bytes_ == 0) {
+ *bytes_read = 0;
+ return true;
+ }
- int result = stream_reader_->Read(
- buf, buf_size,
+ const int result = stream_reader_->Read(
+ buf,
+ std::min(static_cast<int64>(buf_size), remaining_bytes_),
base::Bind(&DriveURLRequestJob::OnReadCompleted,
weak_ptr_factory_.GetWeakPtr()));
@@ -165,35 +356,13 @@ bool DriveURLRequestJob::ReadRawData(
// Reading has been finished immediately.
*bytes_read = result;
+ remaining_bytes_ -= result;
return true;
}
DriveURLRequestJob::~DriveURLRequestJob() {
}
-void DriveURLRequestJob::OnDriveFileStreamReaderInitialized(
- int error, scoped_ptr<ResourceEntry> entry) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(stream_reader_);
-
- if (error != FILE_ERROR_OK) {
- NotifyStartError(
- net::URLRequestStatus(net::URLRequestStatus::FAILED, error));
- return;
- }
-
- DCHECK(entry && entry->has_file_specific_info());
- entry_ = entry.Pass();
-
- if (!entry_->file_specific_info().is_hosted_document()) {
- // We don't need to set content size for hosted documents,
- // because it will be redirected.
- set_expected_content_size(entry_->file_info().size());
- }
-
- NotifyHeadersComplete();
-}
-
void DriveURLRequestJob::OnReadCompleted(int read_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -203,6 +372,7 @@ void DriveURLRequestJob::OnReadCompleted(int read_result) {
read_result));
}
+ remaining_bytes_ -= read_result;
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status.
NotifyReadComplete(read_result);
}

Powered by Google App Engine
This is Rietveld 408576698