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

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

Issue 10069014: Save Page As MHTML (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 8 years, 7 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 | 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 #include "content/browser/download/save_package.h" 5 #include "content/browser/download/save_package.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/file_path.h" 10 #include "base/file_path.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 : content::WebContentsObserver(web_contents), 124 : content::WebContentsObserver(web_contents),
125 file_manager_(NULL), 125 file_manager_(NULL),
126 download_manager_(NULL), 126 download_manager_(NULL),
127 download_(NULL), 127 download_(NULL),
128 page_url_(GetUrlToBeSaved()), 128 page_url_(GetUrlToBeSaved()),
129 saved_main_file_path_(file_full_path), 129 saved_main_file_path_(file_full_path),
130 saved_main_directory_path_(directory_full_path), 130 saved_main_directory_path_(directory_full_path),
131 title_(web_contents->GetTitle()), 131 title_(web_contents->GetTitle()),
132 start_tick_(base::TimeTicks::Now()), 132 start_tick_(base::TimeTicks::Now()),
133 finished_(false), 133 finished_(false),
134 mhtml_finishing_(false),
134 user_canceled_(false), 135 user_canceled_(false),
135 disk_error_occurred_(false), 136 disk_error_occurred_(false),
136 save_type_(save_type), 137 save_type_(save_type),
137 all_save_items_count_(0), 138 all_save_items_count_(0),
138 wait_state_(INITIALIZE), 139 wait_state_(INITIALIZE),
139 contents_id_(web_contents->GetRenderProcessHost()->GetID()), 140 contents_id_(web_contents->GetRenderProcessHost()->GetID()),
140 unique_id_(g_save_package_id++), 141 unique_id_(g_save_package_id++),
141 wrote_to_completed_file_(false), 142 wrote_to_completed_file_(false),
142 wrote_to_failed_file_(false) { 143 wrote_to_failed_file_(false) {
143 DCHECK(page_url_.is_valid()); 144 DCHECK(page_url_.is_valid());
144 DCHECK(save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML || 145 DCHECK((save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
145 save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML); 146 (save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML) ||
147 (save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
146 DCHECK(!saved_main_file_path_.empty() && 148 DCHECK(!saved_main_file_path_.empty() &&
147 saved_main_file_path_.value().length() <= kMaxFilePathLength); 149 saved_main_file_path_.value().length() <= kMaxFilePathLength);
148 DCHECK(!saved_main_directory_path_.empty() && 150 DCHECK(!saved_main_directory_path_.empty() &&
149 saved_main_directory_path_.value().length() < kMaxFilePathLength); 151 saved_main_directory_path_.value().length() < kMaxFilePathLength);
150 InternalInit(); 152 InternalInit();
151 } 153 }
152 154
153 SavePackage::SavePackage(WebContents* web_contents) 155 SavePackage::SavePackage(WebContents* web_contents)
154 : content::WebContentsObserver(web_contents), 156 : content::WebContentsObserver(web_contents),
155 file_manager_(NULL), 157 file_manager_(NULL),
156 download_manager_(NULL), 158 download_manager_(NULL),
157 download_(NULL), 159 download_(NULL),
158 page_url_(GetUrlToBeSaved()), 160 page_url_(GetUrlToBeSaved()),
159 title_(web_contents->GetTitle()), 161 title_(web_contents->GetTitle()),
160 start_tick_(base::TimeTicks::Now()), 162 start_tick_(base::TimeTicks::Now()),
161 finished_(false), 163 finished_(false),
164 mhtml_finishing_(false),
162 user_canceled_(false), 165 user_canceled_(false),
163 disk_error_occurred_(false), 166 disk_error_occurred_(false),
164 save_type_(content::SAVE_PAGE_TYPE_UNKNOWN), 167 save_type_(content::SAVE_PAGE_TYPE_UNKNOWN),
165 all_save_items_count_(0), 168 all_save_items_count_(0),
166 wait_state_(INITIALIZE), 169 wait_state_(INITIALIZE),
167 contents_id_(web_contents->GetRenderProcessHost()->GetID()), 170 contents_id_(web_contents->GetRenderProcessHost()->GetID()),
168 unique_id_(g_save_package_id++), 171 unique_id_(g_save_package_id++),
169 wrote_to_completed_file_(false), 172 wrote_to_completed_file_(false),
170 wrote_to_failed_file_(false) { 173 wrote_to_failed_file_(false) {
171 DCHECK(page_url_.is_valid()); 174 DCHECK(page_url_.is_valid());
172 InternalInit(); 175 InternalInit();
173 } 176 }
174 177
175 // This is for testing use. Set |finished_| as true because we don't want 178 // This is for testing use. Set |finished_| as true because we don't want
176 // method Cancel to be be called in destructor in test mode. 179 // method Cancel to be be called in destructor in test mode.
177 // We also don't call InternalInit(). 180 // We also don't call InternalInit().
178 SavePackage::SavePackage(WebContents* web_contents, 181 SavePackage::SavePackage(WebContents* web_contents,
179 const FilePath& file_full_path, 182 const FilePath& file_full_path,
180 const FilePath& directory_full_path) 183 const FilePath& directory_full_path)
181 : content::WebContentsObserver(web_contents), 184 : content::WebContentsObserver(web_contents),
182 file_manager_(NULL), 185 file_manager_(NULL),
183 download_manager_(NULL), 186 download_manager_(NULL),
184 download_(NULL), 187 download_(NULL),
185 saved_main_file_path_(file_full_path), 188 saved_main_file_path_(file_full_path),
186 saved_main_directory_path_(directory_full_path), 189 saved_main_directory_path_(directory_full_path),
187 start_tick_(base::TimeTicks::Now()), 190 start_tick_(base::TimeTicks::Now()),
188 finished_(true), 191 finished_(true),
192 mhtml_finishing_(false),
189 user_canceled_(false), 193 user_canceled_(false),
190 disk_error_occurred_(false), 194 disk_error_occurred_(false),
191 save_type_(content::SAVE_PAGE_TYPE_UNKNOWN), 195 save_type_(content::SAVE_PAGE_TYPE_UNKNOWN),
192 all_save_items_count_(0), 196 all_save_items_count_(0),
193 wait_state_(INITIALIZE), 197 wait_state_(INITIALIZE),
194 contents_id_(0), 198 contents_id_(0),
195 unique_id_(g_save_package_id++), 199 unique_id_(g_save_package_id++),
196 wrote_to_completed_file_(false), 200 wrote_to_completed_file_(false),
197 wrote_to_failed_file_(false) { 201 wrote_to_failed_file_(false) {
198 } 202 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 262
259 file_manager_ = rdh->save_file_manager(); 263 file_manager_ = rdh->save_file_manager();
260 DCHECK(file_manager_); 264 DCHECK(file_manager_);
261 265
262 download_manager_ = web_contents()->GetBrowserContext()->GetDownloadManager(); 266 download_manager_ = web_contents()->GetBrowserContext()->GetDownloadManager();
263 DCHECK(download_manager_); 267 DCHECK(download_manager_);
264 268
265 download_stats::RecordSavePackageEvent(download_stats::SAVE_PACKAGE_STARTED); 269 download_stats::RecordSavePackageEvent(download_stats::SAVE_PACKAGE_STARTED);
266 } 270 }
267 271
268 bool SavePackage::Init() { 272 bool SavePackage::Init(
273 const content::SavePackageDownloadCreatedCallback&
274 download_created_callback) {
269 // Set proper running state. 275 // Set proper running state.
270 if (wait_state_ != INITIALIZE) 276 if (wait_state_ != INITIALIZE)
271 return false; 277 return false;
272 278
273 wait_state_ = START_PROCESS; 279 wait_state_ = START_PROCESS;
274 280
275 // Initialize the request context and resource dispatcher. 281 // Initialize the request context and resource dispatcher.
276 content::BrowserContext* browser_context = 282 content::BrowserContext* browser_context =
277 web_contents()->GetBrowserContext(); 283 web_contents()->GetBrowserContext();
278 if (!browser_context) { 284 if (!browser_context) {
279 NOTREACHED(); 285 NOTREACHED();
280 return false; 286 return false;
281 } 287 }
282 288
283 // The download manager keeps ownership but adds us as an observer. 289 // The download manager keeps ownership but adds us as an observer.
284 download_ = download_manager_->CreateSavePackageDownloadItem( 290 download_ = download_manager_->CreateSavePackageDownloadItem(
285 saved_main_file_path_, page_url_, 291 saved_main_file_path_,
286 browser_context->IsOffTheRecord(), this); 292 page_url_,
293 browser_context->IsOffTheRecord(),
294 ((save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML) ?
295 "multipart/related" : "text/html"),
296 this);
297 if (!download_created_callback.is_null())
298 download_created_callback.Run(download_);
287 299
288 // Check save type and process the save page job. 300 // Check save type and process the save page job.
289 if (save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML) { 301 if (save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML) {
290 // Get directory 302 // Get directory
291 DCHECK(!saved_main_directory_path_.empty()); 303 DCHECK(!saved_main_directory_path_.empty());
292 GetAllSavableResourceLinksForCurrentPage(); 304 GetAllSavableResourceLinksForCurrentPage();
305 } else if (save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML) {
306 web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind(
307 &SavePackage::OnMHTMLGenerated, this));
293 } else { 308 } else {
294 wait_state_ = NET_FILES; 309 wait_state_ = NET_FILES;
295 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? 310 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ?
296 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : 311 SaveFileCreateInfo::SAVE_FILE_FROM_FILE :
297 SaveFileCreateInfo::SAVE_FILE_FROM_NET; 312 SaveFileCreateInfo::SAVE_FILE_FROM_NET;
298 SaveItem* save_item = new SaveItem(page_url_, 313 SaveItem* save_item = new SaveItem(page_url_,
299 GURL(), 314 GURL(),
300 this, 315 this,
301 save_source); 316 save_source);
302 // Add this item to waiting list. 317 // Add this item to waiting list.
303 waiting_item_queue_.push(save_item); 318 waiting_item_queue_.push(save_item);
304 all_save_items_count_ = 1; 319 all_save_items_count_ = 1;
305 download_->SetTotalBytes(1); 320 download_->SetTotalBytes(1);
306 321
307 DoSavingProcess(); 322 DoSavingProcess();
308 } 323 }
309 324
310 return true; 325 return true;
311 } 326 }
312 327
328 void SavePackage::OnMHTMLGenerated(const FilePath& path, int64 size) {
329 if (size <= 0) {
330 Cancel(false);
331 return;
332 }
333 wrote_to_completed_file_ = true;
334 download_->SetTotalBytes(size);
335 download_->UpdateProgress(size, size, DownloadItem::kEmptyFileHash);
336 // Must call OnAllDataSaved here in order for
337 // GDataDownloadObserver::ShouldUpload() to return true.
338 // ShouldCompleteDownload() may depend on the gdata uploader to finish.
339 download_->OnAllDataSaved(size, DownloadItem::kEmptyFileHash);
340 // GDataDownloadObserver is waiting for the upload to complete. When that
341 // happens, it will call download_->MaybeCompleteDownload(), which will call
342 // through our OnDownloadUpdated() allowing us to Finish().
343 // OnDownloadUpdated() may have been called in OnAllDataSaved(), so |this| may
344 // be deleted at this point.
345 }
346
313 // On POSIX, the length of |pure_file_name| + |file_name_ext| is further 347 // On POSIX, the length of |pure_file_name| + |file_name_ext| is further
314 // restricted by NAME_MAX. The maximum allowed path looks like: 348 // restricted by NAME_MAX. The maximum allowed path looks like:
315 // '/path/to/save_dir' + '/' + NAME_MAX. 349 // '/path/to/save_dir' + '/' + NAME_MAX.
316 uint32 SavePackage::GetMaxPathLengthForDirectory(const FilePath& base_dir) { 350 uint32 SavePackage::GetMaxPathLengthForDirectory(const FilePath& base_dir) {
317 #if defined(OS_POSIX) 351 #if defined(OS_POSIX)
318 return std::min(kMaxFilePathLength, 352 return std::min(kMaxFilePathLength,
319 static_cast<uint32>(base_dir.value().length()) + 353 static_cast<uint32>(base_dir.value().length()) +
320 NAME_MAX + 1); 354 NAME_MAX + 1);
321 #else 355 #else
322 return kMaxFilePathLength; 356 return kMaxFilePathLength;
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 it != saved_failed_items_.end(); ++it) 732 it != saved_failed_items_.end(); ++it)
699 save_ids.push_back(it->second->save_id()); 733 save_ids.push_back(it->second->save_id());
700 734
701 BrowserThread::PostTask( 735 BrowserThread::PostTask(
702 BrowserThread::FILE, FROM_HERE, 736 BrowserThread::FILE, FROM_HERE,
703 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, 737 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap,
704 file_manager_, 738 file_manager_,
705 save_ids)); 739 save_ids));
706 740
707 if (download_) { 741 if (download_) {
708 download_->OnAllDataSaved(all_save_items_count_, 742 if (save_type_ != content::SAVE_PAGE_TYPE_AS_MHTML)
709 DownloadItem::kEmptyFileHash); 743 download_->OnAllDataSaved(all_save_items_count_,
744 DownloadItem::kEmptyFileHash);
710 download_->MarkAsComplete(); 745 download_->MarkAsComplete();
711 FinalizeDownloadEntry(); 746 FinalizeDownloadEntry();
712 } 747 }
713 } 748 }
714 749
715 // Called for updating end state. 750 // Called for updating end state.
716 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) { 751 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) {
717 // Because we might have canceled this saving job before, 752 // Because we might have canceled this saving job before,
718 // so we might not find corresponding SaveItem. Just ignore it. 753 // so we might not find corresponding SaveItem. Just ignore it.
719 SaveItem* save_item = LookupItemInProcessBySaveId(save_id); 754 SaveItem* save_item = LookupItemInProcessBySaveId(save_id);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 802
768 save_item->Finish(0, false); 803 save_item->Finish(0, false);
769 804
770 PutInProgressItemToSavedMap(save_item); 805 PutInProgressItemToSavedMap(save_item);
771 806
772 // Inform the DownloadItem to update UI. 807 // Inform the DownloadItem to update UI.
773 // We use the received bytes as number of saved files. 808 // We use the received bytes as number of saved files.
774 if (download_) 809 if (download_)
775 download_->UpdateProgress(completed_count(), CurrentSpeed(), ""); 810 download_->UpdateProgress(completed_count(), CurrentSpeed(), "");
776 811
777 if (save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML || 812 if ((save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
778 save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM) { 813 (save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML) ||
814 (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM)) {
779 // We got error when saving page. Treat it as disk error. 815 // We got error when saving page. Treat it as disk error.
780 Cancel(true); 816 Cancel(true);
781 } 817 }
782 818
783 if (canceled()) { 819 if (canceled()) {
784 DCHECK(finished_); 820 DCHECK(finished_);
785 return; 821 return;
786 } 822 }
787 823
788 // Continue processing the save page job. 824 // Continue processing the save page job.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 wait_state_ = HTML_DATA; 910 wait_state_ = HTML_DATA;
875 // All non-HTML resources have been finished, start all remaining 911 // All non-HTML resources have been finished, start all remaining
876 // HTML files. 912 // HTML files.
877 SaveNextFile(true); 913 SaveNextFile(true);
878 } 914 }
879 } else if (in_process_count()) { 915 } else if (in_process_count()) {
880 // Continue asking for HTML data. 916 // Continue asking for HTML data.
881 DCHECK(wait_state_ == HTML_DATA); 917 DCHECK(wait_state_ == HTML_DATA);
882 } 918 }
883 } else { 919 } else {
884 // Save as HTML only. 920 // Save as HTML only or MHTML.
885 DCHECK(wait_state_ == NET_FILES); 921 DCHECK(wait_state_ == NET_FILES);
886 DCHECK(save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML); 922 DCHECK((save_type_ == content::SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
923 (save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML));
887 if (waiting_item_queue_.size()) { 924 if (waiting_item_queue_.size()) {
888 DCHECK(all_save_items_count_ == waiting_item_queue_.size()); 925 DCHECK(all_save_items_count_ == waiting_item_queue_.size());
889 SaveNextFile(false); 926 SaveNextFile(false);
890 } 927 }
891 } 928 }
892 } 929 }
893 930
894 bool SavePackage::OnMessageReceived(const IPC::Message& message) { 931 bool SavePackage::OnMessageReceived(const IPC::Message& message) {
895 bool handled = true; 932 bool handled = true;
896 IPC_BEGIN_MESSAGE_MAP(SavePackage, message) 933 IPC_BEGIN_MESSAGE_MAP(SavePackage, message)
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 // The WebContents which owns this SavePackage may have disappeared during 1301 // The WebContents which owns this SavePackage may have disappeared during
1265 // the UI->FILE->UI thread hop of 1302 // the UI->FILE->UI thread hop of
1266 // GetSaveInfo->CreateDirectoryOnFileThread->ContinueGetSaveInfo. 1303 // GetSaveInfo->CreateDirectoryOnFileThread->ContinueGetSaveInfo.
1267 if (!web_contents()) 1304 if (!web_contents())
1268 return; 1305 return;
1269 1306
1270 FilePath::StringType default_extension; 1307 FilePath::StringType default_extension;
1271 if (can_save_as_complete) 1308 if (can_save_as_complete)
1272 default_extension = kDefaultHtmlExtension; 1309 default_extension = kDefaultHtmlExtension;
1273 1310
1274 // On ChromeOS, OnPathPicked is not invoked; SavePackageFilePickerChromeOS
1275 // handles the the save.
1276 download_manager_->delegate()->ChooseSavePath( 1311 download_manager_->delegate()->ChooseSavePath(
1277 web_contents(), suggested_path, default_extension, can_save_as_complete, 1312 web_contents(),
1313 suggested_path,
1314 default_extension,
1315 can_save_as_complete,
1278 base::Bind(&SavePackage::OnPathPicked, AsWeakPtr())); 1316 base::Bind(&SavePackage::OnPathPicked, AsWeakPtr()));
1279 } 1317 }
1280 1318
1281 void SavePackage::OnPathPicked(const FilePath& final_name, 1319 void SavePackage::OnPathPicked(
1282 content::SavePageType type) { 1320 const FilePath& final_name,
1321 content::SavePageType type,
1322 const content::SavePackageDownloadCreatedCallback&
1323 download_created_callback) {
1283 // Ensure the filename is safe. 1324 // Ensure the filename is safe.
1284 saved_main_file_path_ = final_name; 1325 saved_main_file_path_ = final_name;
1285 // TODO(asanka): This call may block on IO and shouldn't be made 1326 // TODO(asanka): This call may block on IO and shouldn't be made
1286 // from the UI thread. See http://crbug.com/61827. 1327 // from the UI thread. See http://crbug.com/61827.
1287 net::GenerateSafeFileName(web_contents()->GetContentsMimeType(), false, 1328 net::GenerateSafeFileName(web_contents()->GetContentsMimeType(), false,
1288 &saved_main_file_path_); 1329 &saved_main_file_path_);
1289 1330
1290 saved_main_directory_path_ = saved_main_file_path_.DirName(); 1331 saved_main_directory_path_ = saved_main_file_path_.DirName();
1291 save_type_ = type; 1332 save_type_ = type;
1292 if (save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML) { 1333 if (save_type_ == content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML) {
1293 // Make new directory for saving complete file. 1334 // Make new directory for saving complete file.
1294 saved_main_directory_path_ = saved_main_directory_path_.Append( 1335 saved_main_directory_path_ = saved_main_directory_path_.Append(
1295 saved_main_file_path_.RemoveExtension().BaseName().value() + 1336 saved_main_file_path_.RemoveExtension().BaseName().value() +
1296 FILE_PATH_LITERAL("_files")); 1337 FILE_PATH_LITERAL("_files"));
1297 } 1338 }
1298 1339
1299 Init(); 1340 Init(download_created_callback);
1300 } 1341 }
1301 1342
1302 void SavePackage::StopObservation() { 1343 void SavePackage::StopObservation() {
1303 DCHECK(download_); 1344 DCHECK(download_);
1304 DCHECK(download_manager_); 1345 DCHECK(download_manager_);
1305 1346
1306 download_->RemoveObserver(this); 1347 download_->RemoveObserver(this);
1307 download_ = NULL; 1348 download_ = NULL;
1308 download_manager_ = NULL; 1349 download_manager_ = NULL;
1309 } 1350 }
1310 1351
1311 void SavePackage::OnDownloadUpdated(DownloadItem* download) { 1352 void SavePackage::OnDownloadUpdated(DownloadItem* download) {
1312 DCHECK(download_); 1353 DCHECK(download_);
1313 DCHECK(download_ == download); 1354 DCHECK(download_ == download);
1314 DCHECK(download_manager_); 1355 DCHECK(download_manager_);
1315 1356
1316 // Check for removal. 1357 // Check for removal.
1317 if (download->GetState() == DownloadItem::REMOVING) 1358 if (download_->GetState() == DownloadItem::REMOVING) {
1318 StopObservation(); 1359 StopObservation();
1360 }
1361
1362 // MHTML saves may need to wait for GData to finish uploading.
1363 if ((save_type_ == content::SAVE_PAGE_TYPE_AS_MHTML) &&
1364 download_->AllDataSaved() &&
1365 !download_->IsComplete() &&
1366 !mhtml_finishing_ &&
1367 download_manager_->delegate()->ShouldCompleteDownload(download_)) {
1368 // Post a task to avoid re-entering OnDownloadUpdated. Set a flag to
1369 // prevent double-calling Finish() in case another OnDownloadUpdated happens
1370 // before Finish() runs.
1371 mhtml_finishing_ = true;
1372 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1373 base::Bind(&SavePackage::Finish, this));
1374 }
1319 } 1375 }
1320 1376
1321 void SavePackage::FinalizeDownloadEntry() { 1377 void SavePackage::FinalizeDownloadEntry() {
1322 DCHECK(download_); 1378 DCHECK(download_);
1323 DCHECK(download_manager_); 1379 DCHECK(download_manager_);
1324 1380
1325 download_manager_->SavePageDownloadFinished(download_); 1381 download_manager_->SavePageDownloadFinished(download_);
1326 StopObservation(); 1382 StopObservation();
1327 } 1383 }
OLDNEW
« no previous file with comments | « content/browser/download/save_package.h ('k') | content/browser/web_contents/web_contents_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698