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

Side by Side Diff: shell/application_manager/network_fetcher.cc

Issue 1011333003: Fix races when the same bits are downloaded from 2 URLs. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "shell/application_manager/network_fetcher.h" 5 #include "shell/application_manager/network_fetcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h"
8 #include "base/files/file.h" 9 #include "base/files/file.h"
9 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
12 #include "base/process/process.h" 13 #include "base/process/process.h"
13 #include "base/stl_util.h" 14 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "crypto/secure_hash.h" 18 #include "crypto/secure_hash.h"
18 #include "crypto/sha2.h" 19 #include "crypto/sha2.h"
19 #include "mojo/common/common_type_converters.h" 20 #include "mojo/common/common_type_converters.h"
20 #include "mojo/common/data_pipe_utils.h" 21 #include "mojo/common/data_pipe_utils.h"
21 #include "mojo/services/network/public/interfaces/network_service.mojom.h" 22 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
22 #include "shell/application_manager/data_pipe_peek.h" 23 #include "shell/application_manager/data_pipe_peek.h"
24 #include "shell/switches.h"
23 25
24 namespace mojo { 26 namespace mojo {
25 namespace shell { 27 namespace shell {
26 28
27 NetworkFetcher::NetworkFetcher(bool disable_cache, 29 NetworkFetcher::NetworkFetcher(bool disable_cache,
28 const GURL& url, 30 const GURL& url,
29 NetworkService* network_service, 31 NetworkService* network_service,
30 const FetchCallback& loader_callback) 32 const FetchCallback& loader_callback)
31 : Fetcher(loader_callback), 33 : Fetcher(loader_callback),
32 disable_cache_(false), 34 disable_cache_(false),
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 111 }
110 // The output is really a vector of unit8, we're cheating by using a string. 112 // The output is really a vector of unit8, we're cheating by using a string.
111 std::string output(crypto::kSHA256Length, 0); 113 std::string output(crypto::kSHA256Length, 0);
112 ctx->Finish(string_as_array(&output), output.size()); 114 ctx->Finish(string_as_array(&output), output.size());
113 output = base::HexEncode(output.c_str(), output.size()); 115 output = base::HexEncode(output.c_str(), output.size());
114 // Using lowercase for compatiblity with sha256sum output. 116 // Using lowercase for compatiblity with sha256sum output.
115 *digest_string = base::StringToLowerASCII(output); 117 *digest_string = base::StringToLowerASCII(output);
116 return true; 118 return true;
117 } 119 }
118 120
119 bool NetworkFetcher::RenameToAppId(const base::FilePath& old_path, 121 bool NetworkFetcher::RenameToAppId(const GURL& url,
122 const base::FilePath& old_path,
120 base::FilePath* new_path) { 123 base::FilePath* new_path) {
121 std::string app_id; 124 std::string app_id;
122 if (!ComputeAppId(old_path, &app_id)) 125 if (!ComputeAppId(old_path, &app_id))
123 return false; 126 return false;
124 127
128 // Using a hash of the url as a directory to prevent a race when the same
129 // bytes are downloaded from 2 different urls.
130 std::string dirname = base::HexEncode(
131 crypto::SHA256HashString(url.spec()).data(), crypto::kSHA256Length);
Nick Bray (chromium) 2015/03/19 17:45:20 It's worth commenting this dirname will not be con
qsr 2015/03/20 11:50:48 done
132
125 base::FilePath temp_dir; 133 base::FilePath temp_dir;
126 base::GetTempDir(&temp_dir); 134 base::GetTempDir(&temp_dir);
135 base::FilePath app_dir = temp_dir.Append(dirname);
136 bool result = base::CreateDirectoryAndGetError(app_dir, nullptr);
Nick Bray (chromium) 2015/03/19 17:45:20 Comment on leaking the directory and why.
qsr 2015/03/20 11:50:49 Done.
137 DCHECK(result);
127 std::string unique_name = base::StringPrintf("%s.mojo", app_id.c_str()); 138 std::string unique_name = base::StringPrintf("%s.mojo", app_id.c_str());
128 *new_path = temp_dir.Append(unique_name); 139 *new_path = app_dir.Append(unique_name);
129 return base::Move(old_path, *new_path); 140 return base::Move(old_path, *new_path);
130 } 141 }
131 142
132 void NetworkFetcher::CopyCompleted( 143 void NetworkFetcher::CopyCompleted(
133 base::Callback<void(const base::FilePath&, bool)> callback, 144 base::Callback<void(const base::FilePath&, bool)> callback,
134 bool success) { 145 bool success) {
135 // The copy completed, now move to $TMP/$APP_ID.mojo before the dlopen.
136 if (success) { 146 if (success) {
137 success = false; 147 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
138 base::FilePath new_path; 148 switches::kPredictableAppFilenames)) {
139 if (RenameToAppId(path_, &new_path)) { 149 // The copy completed, now move to $TMP/$APP_ID.mojo before the dlopen.
140 if (base::PathExists(new_path)) { 150 success = false;
141 path_ = new_path; 151 base::FilePath new_path;
142 success = true; 152 if (RenameToAppId(url_, path_, &new_path)) {
143 RecordCacheToURLMapping(path_, url_); 153 if (base::PathExists(new_path)) {
154 path_ = new_path;
155 success = true;
156 }
144 } 157 }
145 } 158 }
146 } 159 }
147 160
161 if (success)
162 RecordCacheToURLMapping(path_, url_);
163
148 base::MessageLoop::current()->PostTask(FROM_HERE, 164 base::MessageLoop::current()->PostTask(FROM_HERE,
149 base::Bind(callback, path_, success)); 165 base::Bind(callback, path_, success));
150 } 166 }
151 167
152 void NetworkFetcher::AsPath( 168 void NetworkFetcher::AsPath(
153 base::TaskRunner* task_runner, 169 base::TaskRunner* task_runner,
154 base::Callback<void(const base::FilePath&, bool)> callback) { 170 base::Callback<void(const base::FilePath&, bool)> callback) {
155 if (!path_.empty() || !response_) { 171 if (!path_.empty() || !response_) {
156 base::MessageLoop::current()->PostTask( 172 base::MessageLoop::current()->PostTask(
157 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); 173 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_)));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 loader_callback_.Run(make_scoped_ptr<Fetcher>(NULL)); 225 loader_callback_.Run(make_scoped_ptr<Fetcher>(NULL));
210 return; 226 return;
211 } 227 }
212 228
213 response_ = response.Pass(); 229 response_ = response.Pass();
214 loader_callback_.Run(make_scoped_ptr(this)); 230 loader_callback_.Run(make_scoped_ptr(this));
215 } 231 }
216 232
217 } // namespace shell 233 } // namespace shell
218 } // namespace mojo 234 } // namespace mojo
OLDNEW
« no previous file with comments | « shell/application_manager/network_fetcher.h ('k') | shell/switches.h » ('j') | shell/switches.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698