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

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..fdfa1ed70e678c18cca23da71425cd98327d9005 100644
--- a/chrome/browser/chromeos/drive/drive_url_request_job.cc
+++ b/chrome/browser/chromeos/drive/drive_url_request_job.cc
@@ -5,15 +5,18 @@
#include "chrome/browser/chromeos/drive/drive_url_request_job.h"
#include <string>
+#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,12 +24,14 @@
#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;
@@ -44,16 +49,129 @@ std::string FixupMimeType(const std::string& type) {
return type;
}
+// Check if the |url| points a valid position or not.
mtomasz 2014/09/18 07:21:07 nit: position -> file/place/location?
hirono 2014/09/18 08:18:55 Done.
+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;
+ }
+}
} // namespace
-DriveURLRequestJob::DriveURLRequestJob(
- const FileSystemGetter& file_system_getter,
- base::SequencedTaskRunner* file_task_runner,
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate)
+class DriveURLRequestJob::GetFileSystemContextDelegate {
mtomasz 2014/09/18 07:21:07 Class comment is missing.
hirono 2014/09/18 08:18:55 Done.
+ public:
+ GetFileSystemContextDelegate(void* profile_id,
mtomasz 2014/09/18 07:21:07 Can this class be moved to an anonymous namespace?
hirono 2014/09/18 08:18:55 Done.
+ const GURL& url,
+ DelegateCallback callback)
+ : profile_id_(profile_id), url_(url), callback_(callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetFileSystemContextDelegate::RunOnUIThread,
+ base::Unretained(this)));
+ }
+
+ scoped_refptr<storage::FileSystemContext> file_system_context;
mtomasz 2014/09/18 07:21:07 Shall it be public? How about making private and a
hirono 2014/09/18 08:18:55 Done.
+ storage::FileSystemURL file_system_url;
+ std::string mime_type;
+
+ private:
+ void RunOnUIThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ Profile* const profile = reinterpret_cast<Profile*>(profile_id_);
+ if (!g_browser_process->profile_manager()->IsValidProfile(profile)) {
+ LOG(ERROR) << "Profile is invalid.";
+ ReplyResult();
+ return;
+ }
+ content::StoragePartition* const storage =
+ content::BrowserContext::GetStoragePartitionForSite(profile, url_);
+ DCHECK(storage);
+
+ scoped_refptr<storage::FileSystemContext> context =
+ storage->GetFileSystemContext();
+ DCHECK(context);
+
+ // 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)) {
+ LOG(ERROR) << "virtual path does not find.";
+ ReplyResult();
+ return;
+ }
+
+ // Obtain the file system URL.
+ // TODO(hirono): After removing MHTML support, stop to use the special
+ // drive: scheme and use filesystem: URL directly.
mtomasz 2014/09/18 07:21:07 Please add a crbug.com link. This is a large hack
hirono 2014/09/18 08:18:55 Done.
+ file_system_url = context->CreateCrackedFileSystemURL(
+ GURL(std::string(chrome::kDriveScheme) + ":"),
+ storage::kFileSystemTypeExternal,
+ virtual_path);
+ file_system_context = context;
+
+ extensions::app_file_handler_util::GetMimeTypeForLocalPath(
mtomasz 2014/09/18 07:21:07 How about using https://code.google.com/p/chromium
hirono 2014/09/18 08:18:55 I'm not sure. It looks the function called GetMime
mtomasz 2014/09/18 09:22:23 Ah, you're right. However, according to the commen
hirono 2014/09/18 11:03:58 Exactly. I removed the fallback. Thank you!
+ profile,
+ file_system_url.path(),
+ base::Bind(&GetFileSystemContextDelegate::OnGotMimeTypeOnUIThread,
+ base::Unretained(this)));
+ }
+
+ void OnGotMimeTypeOnUIThread(const std::string& mime_type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Detect mime type from the extension.
+ if (mime_type.empty()) {
+ net::GetMimeTypeFromExtension(file_system_url.virtual_path().Extension(),
+ &this->mime_type);
+ } else {
+ this->mime_type = FixupMimeType(mime_type);
+ }
+
+ ReplyResult();
+ }
+
+ void ReplyResult() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback_, base::Passed(make_scoped_ptr(this))));
+ }
+
+ void* const profile_id_;
+ const GURL url_;
+ const DelegateCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetFileSystemContextDelegate);
+};
+
+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),
+ total_bytes_read_(0),
weak_ptr_factory_(this) {
}
@@ -77,7 +195,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 +207,120 @@ 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;
+ }
+
+ // Owned by itself.
+ new GetFileSystemContextDelegate(
+ profile_id_,
+ request()->url(),
+ base::Bind(&DriveURLRequestJob::OnGotDelegate,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DriveURLRequestJob::OnGotDelegate(
+ scoped_ptr<GetFileSystemContextDelegate> delegate) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!delegate->file_system_url.is_valid()) {
+ NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FILE_NOT_FOUND));
+ return;
+ }
+
+ if (!IsValidURL(delegate->file_system_url)) {
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,
+ // Get ownership of the delegate.
+ delegate_ = delegate.Pass();
+
+ // Prepare offset.
+ const int64 offset = byte_range_.HasFirstBytePosition()
+ ? byte_range_.first_byte_position()
+ : 0;
+
+ // Create file stream reader.
+ stream_reader_ = delegate_->file_system_context->CreateFileStreamReader(
+ delegate_->file_system_url, offset, base::Time());
+ if (!stream_reader_) {
+ NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FILE_NOT_FOUND));
+ return;
+ }
+
+ // Check if the entry has a redirect URL.
+ delegate_->file_system_context->external_backend()->GetRedirectURLForContents(
+ delegate_->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.
+ delegate_->file_system_context->operation_runner()->GetMetadata(
+ delegate_->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;
+ }
+ set_expected_content_size(file_info.size);
+
+ NotifyHeadersComplete();
+}
+
void DriveURLRequestJob::Kill() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
stream_reader_.reset();
+ delegate_.reset();
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()));
+ DCHECK(delegate_);
+ mime_type->assign(delegate_->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,12 +329,26 @@ 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_);
- int result = stream_reader_->Read(
- buf, buf_size,
- base::Bind(&DriveURLRequestJob::OnReadCompleted,
- weak_ptr_factory_.GetWeakPtr()));
+ int64 max_size = buf_size;
+ if (byte_range_.HasFirstBytePosition() && byte_range_.HasLastBytePosition()) {
+ int64 remaining_range_size = byte_range_.last_byte_position() -
+ byte_range_.first_byte_position() -
+ total_bytes_read_ + 1;
+ if (remaining_range_size < buf_size)
+ max_size = remaining_range_size;
+ }
+
+ if (max_size <= 0) {
+ *bytes_read = 0;
+ return true;
+ }
+ const int result =
+ stream_reader_->Read(buf,
+ max_size,
+ base::Bind(&DriveURLRequestJob::OnReadCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
if (result == net::ERR_IO_PENDING) {
// The data is not yet available.
@@ -164,36 +362,14 @@ bool DriveURLRequestJob::ReadRawData(
}
// Reading has been finished immediately.
- *bytes_read = result;
+ *bytes_read = result > max_size ? max_size : result;
+ total_bytes_read_ += 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 +379,7 @@ void DriveURLRequestJob::OnReadCompleted(int read_result) {
read_result));
}
+ total_bytes_read_ += read_result;
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status.
NotifyReadComplete(read_result);
}

Powered by Google App Engine
This is Rietveld 408576698