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

Side by Side Diff: content/browser/download/download_item_impl.cc

Issue 11366121: Split DownloadFile::Rename into RenameAndUniquify and RenameAndAnnotate. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync to LKGR. Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // File method ordering: Methods in this file are in the same order as 5 // File method ordering: Methods in this file are in the same order as
6 // in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interfaces Start, MaybeCompleteDownload, and OnDownloadCompleting 7 // interfaces Start, MaybeCompleteDownload, and OnDownloadCompleting
8 // are placed in chronological order with the other (private) routines 8 // are placed in chronological order with the other (private) routines
9 // that together define a DownloadItem's state transitions 9 // that together define a DownloadItem's state transitions
10 // as the download progresses. See "Download progression cascade" later in 10 // as the download progresses. See "Download progression cascade" later in
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 virtual void ResumeRequest() const OVERRIDE {} 92 virtual void ResumeRequest() const OVERRIDE {}
93 virtual void CancelRequest() const OVERRIDE {} 93 virtual void CancelRequest() const OVERRIDE {}
94 virtual std::string DebugString() const OVERRIDE { 94 virtual std::string DebugString() const OVERRIDE {
95 return "Null DownloadRequestHandle"; 95 return "Null DownloadRequestHandle";
96 } 96 }
97 }; 97 };
98 98
99 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that 99 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
100 // takes ownership of the DownloadFile and hence implicitly destroys it 100 // takes ownership of the DownloadFile and hence implicitly destroys it
101 // at the end of the function. 101 // at the end of the function.
102 static void DownloadFileDetach( 102 static void DownloadFileDetach(scoped_ptr<DownloadFile> download_file) {
103 scoped_ptr<DownloadFile> download_file,
104 const DownloadFile::DetachCompletionCallback& callback) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
106 download_file->Detach(callback); 104 download_file->Detach();
107 } 105 }
108 106
109 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) { 107 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
111 download_file->Cancel(); 109 download_file->Cancel();
112 } 110 }
113 111
114 } // namespace 112 } // namespace
115 113
116 // Our download table ID starts at 1, so we use 0 to represent a download that 114 // Our download table ID starts at 1, so we use 0 to represent a download that
(...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 // spurious rename when we can just rename to the final 1065 // spurious rename when we can just rename to the final
1068 // filename. Unnecessary renames may cause bugs like 1066 // filename. Unnecessary renames may cause bugs like
1069 // http://crbug.com/74187. 1067 // http://crbug.com/74187.
1070 DCHECK(!is_save_package_download_); 1068 DCHECK(!is_save_package_download_);
1071 DCHECK(download_file_.get()); 1069 DCHECK(download_file_.get());
1072 DownloadFile::RenameCompletionCallback callback = 1070 DownloadFile::RenameCompletionCallback callback =
1073 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 1071 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
1074 weak_ptr_factory_.GetWeakPtr()); 1072 weak_ptr_factory_.GetWeakPtr());
1075 BrowserThread::PostTask( 1073 BrowserThread::PostTask(
1076 BrowserThread::FILE, FROM_HERE, 1074 BrowserThread::FILE, FROM_HERE,
1077 base::Bind(&DownloadFile::Rename, 1075 base::Bind(&DownloadFile::RenameAndUniquify,
1078 // Safe because we control download file lifetime. 1076 // Safe because we control download file lifetime.
1079 base::Unretained(download_file_.get()), 1077 base::Unretained(download_file_.get()),
1080 intermediate_path, false, callback)); 1078 intermediate_path, callback));
1081 } 1079 }
1082 1080
1083 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1081 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1084 DownloadInterruptReason reason, 1082 DownloadInterruptReason reason,
1085 const FilePath& full_path) { 1083 const FilePath& full_path) {
1086 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1084 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1087 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1085 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1088 Interrupt(reason); 1086 Interrupt(reason);
1089 } else { 1087 } else {
1090 SetFullPath(full_path); 1088 SetFullPath(full_path);
1091 UpdateObservers(); 1089 UpdateObservers();
1092 } 1090 }
1093 1091
1094 delegate_->DownloadRenamedToIntermediateName(this); 1092 delegate_->DownloadRenamedToIntermediateName(this);
1095 } 1093 }
1096 1094
1097 // When SavePackage downloads MHTML to GData (see 1095 // When SavePackage downloads MHTML to GData (see
1098 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 1096 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
1099 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 1097 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
1100 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 1098 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
1101 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 1099 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
1102 // notices that the upload has completed and runs its normal Finish() pathway. 1100 // notices that the upload has completed and runs its normal Finish() pathway.
1103 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 1101 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
1104 // downloads. SavePackage always uses its own Finish() to mark downloads 1102 // downloads. SavePackage always uses its own Finish() to mark downloads
1105 // complete. 1103 // complete.
1106 void DownloadItemImpl::MaybeCompleteDownload() { 1104 void DownloadItemImpl::MaybeCompleteDownload() {
1107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1106 DCHECK(!is_save_package_download_);
1108 1107
1109 if (!IsDownloadReadyForCompletion()) 1108 if (!IsDownloadReadyForCompletion())
1110 return; 1109 return;
1111 1110
1112 // TODO(rdsmith): DCHECK that we only pass through this point 1111 // TODO(rdsmith): DCHECK that we only pass through this point
1113 // once per download. The natural way to do this is by a state 1112 // once per download. The natural way to do this is by a state
1114 // transition on the DownloadItem. 1113 // transition on the DownloadItem.
1115 1114
1116 // Confirm we're in the proper set of states to be here; 1115 // Confirm we're in the proper set of states to be here;
1117 // have all data, have a history handle, (validated or safe). 1116 // have all data, have a history handle, (validated or safe).
(...skipping 19 matching lines...) Expand all
1137 delegate_->ReadyForDownloadCompletion( 1136 delegate_->ReadyForDownloadCompletion(
1138 this, base::Bind(&DownloadItemImpl::ReadyForDownloadCompletionDone, 1137 this, base::Bind(&DownloadItemImpl::ReadyForDownloadCompletionDone,
1139 weak_ptr_factory_.GetWeakPtr())); 1138 weak_ptr_factory_.GetWeakPtr()));
1140 } 1139 }
1141 1140
1142 void DownloadItemImpl::ReadyForDownloadCompletionDone() { 1141 void DownloadItemImpl::ReadyForDownloadCompletionDone() {
1143 if (state_ != IN_PROGRESS_INTERNAL) 1142 if (state_ != IN_PROGRESS_INTERNAL)
1144 return; 1143 return;
1145 1144
1146 VLOG(20) << __FUNCTION__ << "()" 1145 VLOG(20) << __FUNCTION__ << "()"
1147 << " needs rename = " << NeedsRename()
1148 << " " << DebugString(true); 1146 << " " << DebugString(true);
1149 DCHECK(!GetTargetFilePath().empty()); 1147 DCHECK(!GetTargetFilePath().empty());
1150 DCHECK_NE(DANGEROUS, GetSafetyState()); 1148 DCHECK_NE(DANGEROUS, GetSafetyState());
1151 1149
1152 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration. 1150 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
1153 if (is_save_package_download_) { 1151 if (is_save_package_download_) {
1154 // Avoid doing anything on the file thread; there's nothing we control 1152 // Avoid doing anything on the file thread; there's nothing we control
1155 // there. 1153 // there.
1156 OnDownloadFileReleased(DOWNLOAD_INTERRUPT_REASON_NONE); 1154 // Strictly speaking, this skips giving the embedder a chance to open
1155 // the download. But on a save package download, there's no real
1156 // concept of opening.
1157 Completed();
1157 return; 1158 return;
1158 } 1159 }
1159 1160
1160 DCHECK(download_file_.get()); 1161 DCHECK(download_file_.get());
1161 if (NeedsRename()) { 1162 // Unilaterally rename; even if it already has the right name,
1162 DownloadFile::RenameCompletionCallback callback = 1163 // we need theannotation.
1163 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1164 DownloadFile::RenameCompletionCallback callback =
1164 weak_ptr_factory_.GetWeakPtr()); 1165 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1165 BrowserThread::PostTask( 1166 weak_ptr_factory_.GetWeakPtr());
1166 BrowserThread::FILE, FROM_HERE, 1167 BrowserThread::PostTask(
1167 base::Bind(&DownloadFile::Rename, 1168 BrowserThread::FILE, FROM_HERE,
1168 base::Unretained(download_file_.get()), 1169 base::Bind(&DownloadFile::RenameAndAnnotate,
1169 GetTargetFilePath(), true, callback)); 1170 base::Unretained(download_file_.get()),
1170 } else { 1171 GetTargetFilePath(), callback));
1171 ReleaseDownloadFile();
1172 }
1173 } 1172 }
1174 1173
1175 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1174 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1176 DownloadInterruptReason reason, 1175 DownloadInterruptReason reason,
1177 const FilePath& full_path) { 1176 const FilePath& full_path) {
1178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1178 DCHECK(!is_save_package_download_);
1179 1179
1180 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which 1180 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which
1181 // will result in deleting the file on the file thread. So we don't 1181 // will result in deleting the file on the file thread. So we don't
1182 // care about the name having been changed. 1182 // care about the name having been changed.
1183 if (state_ != IN_PROGRESS_INTERNAL) 1183 if (state_ != IN_PROGRESS_INTERNAL)
1184 return; 1184 return;
1185 1185
1186 VLOG(20) << __FUNCTION__ << "()" 1186 VLOG(20) << __FUNCTION__ << "()"
1187 << " full_path = \"" << full_path.value() << "\"" 1187 << " full_path = \"" << full_path.value() << "\""
1188 << " needed rename = " << NeedsRename()
1189 << " " << DebugString(false); 1188 << " " << DebugString(false);
1190 DCHECK(NeedsRename());
1191 1189
1192 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1190 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1193 Interrupt(reason); 1191 Interrupt(reason);
1194 return; 1192 return;
1195 } 1193 }
1196 1194
1197 // full_path is now the current and target file path. 1195 DCHECK(target_path_ == full_path);
1198 DCHECK(!full_path.empty());
1199 target_path_ = full_path;
1200 SetFullPath(full_path);
1201 delegate_->DownloadRenamedToFinalName(this);
1202 1196
1203 ReleaseDownloadFile(); 1197 if (full_path != current_path_) {
1204 } 1198 // full_path is now the current and target file path.
1199 DCHECK(!full_path.empty());
1200 SetFullPath(full_path);
1201 delegate_->DownloadRenamedToFinalName(this);
1202 }
1205 1203
1206 void DownloadItemImpl::ReleaseDownloadFile() {
1207 // Complete the download and release the DownloadFile. 1204 // Complete the download and release the DownloadFile.
1208 DCHECK(!is_save_package_download_);
1209 DCHECK(download_file_.get()); 1205 DCHECK(download_file_.get());
1210 BrowserThread::PostTask( 1206 BrowserThread::PostTask(
1211 BrowserThread::FILE, FROM_HERE, 1207 BrowserThread::FILE, FROM_HERE,
1212 base::Bind(&DownloadFileDetach, base::Passed(download_file_.Pass()), 1208 base::Bind(&DownloadFileDetach, base::Passed(download_file_.Pass())));
1213 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1214 weak_ptr_factory_.GetWeakPtr())));
1215 1209
1216 // We're not completely done with the download item yet, but at this 1210 // We're not completely done with the download item yet, but at this
1217 // point we're committed to complete the download. Cancels (or Interrupts, 1211 // point we're committed to complete the download. Cancels (or Interrupts,
1218 // though it's not clear how they could happen) after this point will be 1212 // though it's not clear how they could happen) after this point will be
1219 // ignored. 1213 // ignored.
1220 TransitionTo(COMPLETING_INTERNAL); 1214 TransitionTo(COMPLETING_INTERNAL);
1221 }
1222 1215
1223 void DownloadItemImpl::OnDownloadFileReleased(DownloadInterruptReason reason) {
1224 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1225 Interrupt(reason);
1226 return;
1227 }
1228 if (delegate_->ShouldOpenDownload( 1216 if (delegate_->ShouldOpenDownload(
1229 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened, 1217 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
1230 weak_ptr_factory_.GetWeakPtr()))) { 1218 weak_ptr_factory_.GetWeakPtr()))) {
1231 Completed(); 1219 Completed();
1232 } else { 1220 } else {
1233 delegate_delayed_complete_ = true; 1221 delegate_delayed_complete_ = true;
1234 } 1222 }
1235 } 1223 }
1236 1224
1237 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1225 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 // Somewhat counter-intuitively, it is possible for us to receive an 1261 // Somewhat counter-intuitively, it is possible for us to receive an
1274 // interrupt after we've already been interrupted. The generation of 1262 // interrupt after we've already been interrupted. The generation of
1275 // interrupts from the file thread Renames and the generation of 1263 // interrupts from the file thread Renames and the generation of
1276 // interrupts from disk writes go through two different mechanisms (driven 1264 // interrupts from disk writes go through two different mechanisms (driven
1277 // by rename requests from UI thread and by write requests from IO thread, 1265 // by rename requests from UI thread and by write requests from IO thread,
1278 // respectively), and since we choose not to keep state on the File thread, 1266 // respectively), and since we choose not to keep state on the File thread,
1279 // this is the place where the races collide. It's also possible for 1267 // this is the place where the races collide. It's also possible for
1280 // interrupts to race with cancels. 1268 // interrupts to race with cancels.
1281 1269
1282 // Whatever happens, the first one to hit the UI thread wins. 1270 // Whatever happens, the first one to hit the UI thread wins.
1283 if (state_ != IN_PROGRESS_INTERNAL && state_ != COMPLETING_INTERNAL) 1271 if (state_ != IN_PROGRESS_INTERNAL)
1284 return; 1272 return;
1285 1273
1286 last_reason_ = reason; 1274 last_reason_ = reason;
1287 TransitionTo(INTERRUPTED_INTERNAL); 1275 TransitionTo(INTERRUPTED_INTERNAL);
1288 1276
1289 CancelDownloadFile(); 1277 CancelDownloadFile();
1290 1278
1291 // Cancel the originating URL request. 1279 // Cancel the originating URL request.
1292 request_handle_->CancelRequest(); 1280 request_handle_->CancelRequest();
1293 1281
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 1314
1327 // If the download hasn't been inserted into the history system 1315 // If the download hasn't been inserted into the history system
1328 // (which occurs strictly after file name determination, intermediate 1316 // (which occurs strictly after file name determination, intermediate
1329 // file rename, and UI display) then it's not ready for completion. 1317 // file rename, and UI display) then it's not ready for completion.
1330 if (!IsPersisted()) 1318 if (!IsPersisted())
1331 return false; 1319 return false;
1332 1320
1333 return true; 1321 return true;
1334 } 1322 }
1335 1323
1336 bool DownloadItemImpl::NeedsRename() const {
1337 DCHECK(target_path_.DirName() == current_path_.DirName());
1338 return target_path_ != current_path_;
1339 }
1340
1341 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { 1324 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1342 if (state_ == new_state) 1325 if (state_ == new_state)
1343 return; 1326 return;
1344 1327
1345 DownloadInternalState old_state = state_; 1328 DownloadInternalState old_state = state_;
1346 state_ = new_state; 1329 state_ = new_state;
1347 1330
1348 switch (state_) { 1331 switch (state_) {
1349 case COMPLETING_INTERNAL: 1332 case COMPLETING_INTERNAL:
1350 bound_net_log_.AddEvent( 1333 bound_net_log_.AddEvent(
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 return "CANCELLED"; 1449 return "CANCELLED";
1467 case INTERRUPTED_INTERNAL: 1450 case INTERRUPTED_INTERNAL:
1468 return "INTERRUPTED"; 1451 return "INTERRUPTED";
1469 default: 1452 default:
1470 NOTREACHED() << "Unknown download state " << state; 1453 NOTREACHED() << "Unknown download state " << state;
1471 return "unknown"; 1454 return "unknown";
1472 }; 1455 };
1473 } 1456 }
1474 1457
1475 } // namespace content 1458 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_item_impl.h ('k') | content/browser/download/download_item_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698