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
3 // found in the LICENSE file.
5 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
14 #include "content/public/browser/web_contents.h"
15 #include "net/base/filename_util.h"
17 namespace offline_pages
{
19 const base::FilePath::CharType kMHTMLExtension
[] = FILE_PATH_LITERAL("mhtml");
20 const base::FilePath::CharType kDefaultFileName
[] =
21 FILE_PATH_LITERAL("offline_page");
23 base::FilePath
GenerateFileName(GURL url
, base::string16 title
) {
24 return net::GenerateFileName(url
,
25 std::string(), // content disposition
26 std::string(), // charset
27 base::UTF16ToUTF8(title
), // suggested name
28 std::string(), // mime-type
30 .AddExtension(kMHTMLExtension
);
35 OfflinePageMHTMLArchiver::OfflinePageMHTMLArchiver(
36 content::WebContents
* web_contents
,
37 const base::FilePath
& archive_dir
)
38 : archive_dir_(archive_dir
),
39 web_contents_(web_contents
),
40 weak_ptr_factory_(this) {
41 DCHECK(web_contents_
);
44 OfflinePageMHTMLArchiver::OfflinePageMHTMLArchiver(
45 const base::FilePath
& archive_dir
)
46 : archive_dir_(archive_dir
),
47 web_contents_(nullptr),
48 weak_ptr_factory_(this) {
51 OfflinePageMHTMLArchiver::~OfflinePageMHTMLArchiver() {
53 OfflinePageWebContentsObserver
* web_contents_observer
=
54 OfflinePageWebContentsObserver::FromWebContents(web_contents_
);
55 if (web_contents_observer
)
56 web_contents_observer
->set_main_frame_document_loaded_callback(
61 void OfflinePageMHTMLArchiver::CreateArchive(
62 const CreateArchiveCallback
& callback
) {
63 DCHECK(callback_
.is_null());
64 DCHECK(!callback
.is_null());
70 void OfflinePageMHTMLArchiver::GenerateMHTML() {
71 if (archive_dir_
.empty()) {
72 DVLOG(1) << "Archive path was empty. Can't create archive.";
73 ReportFailure(ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED
);
78 DVLOG(1) << "WebContents is missing. Can't create archive.";
79 ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE
);
83 OfflinePageWebContentsObserver
* web_contents_observer
=
84 OfflinePageWebContentsObserver::FromWebContents(web_contents_
);
85 if (!web_contents_observer
) {
86 DVLOG(1) << "WebContentsObserver is missing. Can't create archive.";
87 ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE
);
91 // If main frame document has not been loaded yet, wait until it is.
92 if (!web_contents_observer
->is_document_loaded_in_main_frame()) {
93 web_contents_observer
->set_main_frame_document_loaded_callback(
94 base::Bind(&OfflinePageMHTMLArchiver::DoGenerateMHTML
,
95 weak_ptr_factory_
.GetWeakPtr()));
102 void OfflinePageMHTMLArchiver::DoGenerateMHTML() {
103 // TODO(fgorski): Figure out if the actual URL can be different at
104 // the end of MHTML generation. Perhaps we should pull it out after the MHTML
106 GURL
url(web_contents_
->GetLastCommittedURL());
107 base::string16
title(web_contents_
->GetTitle());
108 base::FilePath
file_path(archive_dir_
.Append(GenerateFileName(url
, title
)));
110 web_contents_
->GenerateMHTML(
111 file_path
, base::Bind(&OfflinePageMHTMLArchiver::OnGenerateMHTMLDone
,
112 weak_ptr_factory_
.GetWeakPtr(), url
, file_path
));
115 void OfflinePageMHTMLArchiver::OnGenerateMHTMLDone(
117 const base::FilePath
& file_path
,
120 ReportFailure(ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED
);
122 callback_
.Run(this, ArchiverResult::SUCCESSFULLY_CREATED
, url
, file_path
,
127 void OfflinePageMHTMLArchiver::ReportFailure(ArchiverResult result
) {
128 DCHECK(result
!= ArchiverResult::SUCCESSFULLY_CREATED
);
129 callback_
.Run(this, result
, GURL(), base::FilePath(), 0);
132 } // namespace offline_pages