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

Unified Diff: content/browser/loader/temporary_file_manager.cc

Issue 82273002: Fix various issues in RedirectToFileResourceHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments Created 7 years 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: content/browser/loader/temporary_file_manager.cc
diff --git a/content/browser/loader/temporary_file_manager.cc b/content/browser/loader/temporary_file_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8979270a48799c84bff4eea8308dad75038fc563
--- /dev/null
+++ b/content/browser/loader/temporary_file_manager.cc
@@ -0,0 +1,154 @@
+// Copyright 2013 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 "content/browser/loader/temporary_file_manager.h"
+
+#include "base/files/file_util_proxy.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/file_stream.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+
+using webkit_blob::ShareableFileReference;
+
+namespace content {
+
+namespace {
+
+void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
+ const base::FilePath& path) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
+ child_id, path);
+}
+
+} // namespace
+
+struct TemporaryFileManager::PendingTemporary {
+ int child_id;
+ int request_id;
+ TemporaryFileStreamFactory::Callback callback;
+ bool cancelled;
mmenke 2013/12/04 20:55:48 nit: Methods go before member variables.
davidben 2013/12/04 22:44:04 Done.
+
+ PendingTemporary(int child_id,
+ int request_id,
+ const TemporaryFileStreamFactory::Callback& callback)
+ : child_id(child_id),
+ request_id(request_id),
+ callback(callback),
+ cancelled(false) {
+ }
+};
+
+TemporaryFileManager::TemporaryFileManager() : weak_factory_(this) {
+}
+
+TemporaryFileManager::~TemporaryFileManager() {
+}
+
+void TemporaryFileManager::UnregisterDownloadedTempFile(
+ int child_id, int request_id) {
+ DeletableFilesMap& map = registered_temp_files_[child_id];
+ DeletableFilesMap::iterator found = map.find(request_id);
+ if (found != map.end()) {
+ map.erase(found);
+ }
+
+ // Cancel any pending requests.
+ PendingTemporaryMap::iterator found_pending =
+ pending_temporary_map_.find(GlobalRequestID(child_id, request_id));
+ if (found_pending != pending_temporary_map_.end()) {
+ found_pending->second->cancelled = true;
+ }
+
+ // Note that we don't remove the security bits here. This will be done
+ // when all file refs are deleted (see RegisterDownloadedTempFile).
+}
+
+void TemporaryFileManager::UnregisterFilesForChild(int child_id) {
+ registered_temp_files_.erase(child_id);
+
+ // Cancel all pending requests.
+ PendingTemporaryMap::iterator iter =
+ pending_temporary_map_.lower_bound(GlobalRequestID(child_id, -1));
+ PendingTemporaryMap::iterator stop =
+ pending_temporary_map_.lower_bound(GlobalRequestID(child_id + 1, -1));
+ for (; iter != stop; ++iter) {
+ DCHECK_EQ(child_id, iter->first.child_id);
+ iter->second->cancelled = true;
+ }
+}
+
+void TemporaryFileManager::CreateTemporary(
+ int child_id,
+ int request_id,
+ const TemporaryFileStreamFactory::Callback& callback) {
+ PendingTemporary* pending =
+ new PendingTemporary(child_id, request_id, callback);
+ pending_temporary_map_[GlobalRequestID(child_id, request_id)] = pending;
+
+ base::FileUtilProxy::CreateTemporary(
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
+ base::PLATFORM_FILE_ASYNC,
+ base::Bind(&TemporaryFileManager::DidCreateTemporaryFile, AsWeakPtr(),
+ base::Owned(pending)));
+}
+
+void TemporaryFileManager::DidCreateTemporaryFile(
+ TemporaryFileManager::PendingTemporary* pending,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file_handle,
+ const base::FilePath& file_path) {
+ DCHECK_EQ(pending,
+ pending_temporary_map_[GlobalRequestID(pending->child_id,
+ pending->request_id)]);
+ pending_temporary_map_.erase(GlobalRequestID(pending->child_id,
+ pending->request_id));
+
+ if (error_code != base::PLATFORM_FILE_OK) {
+ if (!pending->cancelled)
+ pending->callback.Run(error_code, scoped_ptr<net::FileStream>(), NULL);
+ return;
+ }
+
+ // Cancelled or not, create the deletable_file so the temporary is cleaned up.
+ scoped_refptr<ShareableFileReference> deletable_file =
+ ShareableFileReference::GetOrCreate(
+ file_path,
+ ShareableFileReference::DELETE_ON_FINAL_RELEASE,
+ BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::FILE).get());
+
+ if (pending->cancelled)
+ return;
+
+ scoped_ptr<net::FileStream> file_stream(new net::FileStream(
+ file_handle.ReleaseValue(),
+ base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC,
+ NULL));
+
+ RegisterDownloadedTempFile(pending->child_id, pending->request_id,
+ deletable_file.get());
+ pending->callback.Run(error_code, file_stream.Pass(), deletable_file);
+}
+
+void TemporaryFileManager::RegisterDownloadedTempFile(
+ int child_id, int request_id, ShareableFileReference* reference) {
+ registered_temp_files_[child_id][request_id] = reference;
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
+ child_id, reference->path());
+
+ // When the temp file is deleted, revoke permissions that the renderer has
+ // to that file. This covers an edge case where the file is deleted and then
+ // the same name is re-used for some other purpose, we don't want the old
+ // renderer to still have access to it.
+ //
+ // We do this when the file is deleted because the renderer can take a blob
+ // reference to the temp file that outlives the url loaded that it was
+ // loaded with to keep the file (and permissions) alive.
+ reference->AddFinalReleaseCallback(
+ base::Bind(&RemoveDownloadFileFromChildSecurityPolicy,
+ child_id));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698