summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli <jianli@chromium.org>2015-07-28 16:19:19 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-28 23:19:51 +0000
commit51172d27fefca69971769cd1e6304a9cd1a81884 (patch)
tree552a388481a5294f43e27c222dd003962a60c88c
parentf88efde342905afe8861f38690c6641a14469a60 (diff)
downloadchromium_src-51172d27fefca69971769cd1e6304a9cd1a81884.zip
chromium_src-51172d27fefca69971769cd1e6304a9cd1a81884.tar.gz
chromium_src-51172d27fefca69971769cd1e6304a9cd1a81884.tar.bz2
Hook up with web contents observer in OfflinePageMHTMLArchiver
BUG=491352 TEST=new tests Review URL: https://codereview.chromium.org/1260103002 Cr-Commit-Position: refs/heads/master@{#340800}
-rw-r--r--chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc40
-rw-r--r--chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h28
-rw-r--r--chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc40
-rw-r--r--chrome/browser/android/offline_pages/offline_page_web_contents_observer.cc52
-rw-r--r--chrome/browser/android/offline_pages/offline_page_web_contents_observer.h55
-rw-r--r--chrome/browser/android/offline_pages/offline_page_web_contents_observer_unittest.cc235
-rw-r--r--chrome/browser/ui/tab_helpers.cc3
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
9 files changed, 416 insertions, 40 deletions
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc
index c035825..90ff9d1 100644
--- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc
+++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc
@@ -10,6 +10,7 @@
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
#include "content/public/browser/web_contents.h"
namespace offline_pages {
@@ -35,6 +36,13 @@ OfflinePageMHTMLArchiver::OfflinePageMHTMLArchiver(
}
OfflinePageMHTMLArchiver::~OfflinePageMHTMLArchiver() {
+ if (web_contents_) {
+ OfflinePageWebContentsObserver* web_contents_observer =
+ OfflinePageWebContentsObserver::FromWebContents(web_contents_);
+ if (web_contents_observer)
+ web_contents_observer->set_main_frame_document_loaded_callback(
+ base::Closure());
+ }
}
void OfflinePageMHTMLArchiver::CreateArchive(
@@ -43,26 +51,36 @@ void OfflinePageMHTMLArchiver::CreateArchive(
DCHECK(!callback.is_null());
callback_ = callback;
- if (!IsWebContentsValid()) {
- DVLOG(1) << "WebContents is invalid. Can't create archive.";
- ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
- return;
- }
-
GenerateMHTML();
}
-bool OfflinePageMHTMLArchiver::IsWebContentsValid() const {
- // TODO(fgorski): Make sure that web_contents is valid (use WCObserver).
- return true;
-}
-
void OfflinePageMHTMLArchiver::GenerateMHTML() {
if (!web_contents_) {
DVLOG(1) << "WebContents is missing. Can't create archive.";
ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
return;
}
+
+ OfflinePageWebContentsObserver* web_contents_observer =
+ OfflinePageWebContentsObserver::FromWebContents(web_contents_);
+ if (!web_contents_observer) {
+ DVLOG(1) << "WebContentsObserver is missing. Can't create archive.";
+ ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
+ return;
+ }
+
+ // If main frame document has not been loaded yet, wait until it is.
+ if (!web_contents_observer->is_document_loaded_in_main_frame()) {
+ web_contents_observer->set_main_frame_document_loaded_callback(
+ base::Bind(&OfflinePageMHTMLArchiver::DoGenerateMHTML,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ DoGenerateMHTML();
+}
+
+void OfflinePageMHTMLArchiver::DoGenerateMHTML() {
// TODO(fgorski): Figure out if the actual URL or title can be different at
// the end of MHTML generation. Perhaps we should pull it out after the MHTML
// is generated.
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h
index b00d391..f66522d 100644
--- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h
+++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h
@@ -22,7 +22,6 @@ class WebContents;
} // namespace content
namespace offline_pages {
-class TestMHTMLArchiver;
// Class implementing an offline page archiver using MHTML as an archive format.
//
@@ -49,14 +48,25 @@ class OfflinePageMHTMLArchiver : public OfflinePageArchiver {
// OfflinePageArchiver implementation:
void CreateArchive(const CreateArchiveCallback& callback) override;
- private:
- friend class offline_pages::TestMHTMLArchiver;
-
+ protected:
// Allows to overload the archiver for testing.
OfflinePageMHTMLArchiver(
const base::FilePath& file_path,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ // Try to generate MHTML.
+ // Might be overridden for testing purpose.
+ virtual void GenerateMHTML();
+
+ // Actual call to generate MHTML.
+ // Might be overridden for testing purpose.
+ virtual void DoGenerateMHTML();
+
+ // Callback for Generating MHTML.
+ void OnGenerateMHTMLDone(const GURL& url,
+ const base::string16& title,
+ int64 file_size);
+
// Sends the result of archiving a page to the client that requested archive
// creation.
void ReportResult(ArchiverResult result,
@@ -65,15 +75,7 @@ class OfflinePageMHTMLArchiver : public OfflinePageArchiver {
int64 file_size);
void ReportFailure(ArchiverResult result);
- // Checks that |web_contents_| is still valid.
- virtual bool IsWebContentsValid() const;
- // Actual call to generate MHTML.
- virtual void GenerateMHTML();
- // Callback for Generating MHTML.
- void OnGenerateMHTMLDone(const GURL& url,
- const base::string16& title,
- int64 file_size);
-
+ private:
// Path to the archive file.
const base::FilePath file_path_;
// Contents of the web page to be serialized. Not owned.
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc
index 84cfb8d..0b01879 100644
--- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc
+++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc
@@ -12,17 +12,19 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
+#include "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace offline_pages {
namespace {
+
const char kTestURL[] = "http://example.com/";
const base::string16 kTestTitle = base::ASCIIToUTF16("Test page title");
const base::FilePath::CharType kTestFilePath[] = FILE_PATH_LITERAL(
"/archive_dir/offline_page.mhtml");
const int64 kTestFileSize = 123456LL;
-} // namespace
class TestMHTMLArchiver : public OfflinePageMHTMLArchiver {
public:
@@ -41,7 +43,6 @@ class TestMHTMLArchiver : public OfflinePageMHTMLArchiver {
~TestMHTMLArchiver() override;
private:
- bool IsWebContentsValid() const override;
void GenerateMHTML() override;
const GURL url_;
@@ -66,22 +67,28 @@ TestMHTMLArchiver::TestMHTMLArchiver(
TestMHTMLArchiver::~TestMHTMLArchiver() {
}
-bool TestMHTMLArchiver::IsWebContentsValid() const {
- return test_scenario_ != TestScenario::WEB_CONTENTS_MISSING;
-}
-
void TestMHTMLArchiver::GenerateMHTML() {
- int64 file_size = kTestFileSize;
- if (test_scenario_ == TestScenario::NOT_ABLE_TO_ARCHIVE)
- file_size = -1;
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&TestMHTMLArchiver::OnGenerateMHTMLDone,
- base::Unretained(this),
- url_,
- title_,
- file_size));
+ if (test_scenario_ == TestScenario::WEB_CONTENTS_MISSING) {
+ ReportFailure(ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
+ return;
+ }
+
+ if (test_scenario_ == TestScenario::NOT_ABLE_TO_ARCHIVE) {
+ ReportFailure(ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED);
+ return;
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&TestMHTMLArchiver::OnGenerateMHTMLDone,
+ base::Unretained(this),
+ url_,
+ title_,
+ kTestFileSize));
}
+} // namespace
+
class OfflinePageMHTMLArchiverTest : public testing::Test {
public:
OfflinePageMHTMLArchiverTest();
@@ -148,7 +155,8 @@ scoped_ptr<TestMHTMLArchiver> OfflinePageMHTMLArchiverTest::CreateArchiver(
const base::string16& title,
TestMHTMLArchiver::TestScenario scenario) {
return scoped_ptr<TestMHTMLArchiver>(new TestMHTMLArchiver(
- url, title, scenario, GetTestFilePath(), message_loop_.task_runner()));
+ url, title, scenario, GetTestFilePath(),
+ base::ThreadTaskRunnerHandle::Get()));
}
void OfflinePageMHTMLArchiverTest::OnCreateArchiveDone(
diff --git a/chrome/browser/android/offline_pages/offline_page_web_contents_observer.cc b/chrome/browser/android/offline_pages/offline_page_web_contents_observer.cc
new file mode 100644
index 0000000..57b1679
--- /dev/null
+++ b/chrome/browser/android/offline_pages/offline_page_web_contents_observer.cc
@@ -0,0 +1,52 @@
+// Copyright 2015 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 "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
+
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+ offline_pages::OfflinePageWebContentsObserver);
+
+namespace offline_pages {
+
+OfflinePageWebContentsObserver::OfflinePageWebContentsObserver(
+ content::WebContents* web_contents)
+ : content::WebContentsObserver(web_contents),
+ is_document_loaded_in_main_frame_(false) {
+}
+
+OfflinePageWebContentsObserver::~OfflinePageWebContentsObserver() {
+}
+
+void OfflinePageWebContentsObserver::DocumentLoadedInFrame(
+ content::RenderFrameHost* render_frame_host) {
+ if (!render_frame_host->GetParent()) {
+ is_document_loaded_in_main_frame_ = true;
+ if (!main_frame_document_loaded_callback_.is_null())
+ main_frame_document_loaded_callback_.Run();
+ }
+}
+
+void OfflinePageWebContentsObserver::DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) {
+ if (details.is_navigation_to_different_page())
+ is_document_loaded_in_main_frame_ = false;
+}
+
+void OfflinePageWebContentsObserver::RenderProcessGone(
+ base::TerminationStatus status) {
+ CleanUp();
+}
+
+void OfflinePageWebContentsObserver::CleanUp() {
+ content::WebContentsObserver::Observe(nullptr);
+}
+
+} // namespace offline_pages
diff --git a/chrome/browser/android/offline_pages/offline_page_web_contents_observer.h b/chrome/browser/android/offline_pages/offline_page_web_contents_observer.h
new file mode 100644
index 0000000..81e11f3
--- /dev/null
+++ b/chrome/browser/android/offline_pages/offline_page_web_contents_observer.h
@@ -0,0 +1,55 @@
+// Copyright 2015 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.
+
+#ifndef CHROME_BROWSER_ANDROID_OFFLINE_PAGES_OFFLINE_PAGE_WEB_CONTENTS_OBSERVER_H_
+#define CHROME_BROWSER_ANDROID_OFFLINE_PAGES_OFFLINE_PAGE_WEB_CONTENTS_OBSERVER_H_
+
+#include "base/callback.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace offline_pages {
+
+// Observes activities occurred in the page that is to be archived.
+class OfflinePageWebContentsObserver
+ : public content::WebContentsObserver,
+ public content::WebContentsUserData<OfflinePageWebContentsObserver> {
+ public:
+ ~OfflinePageWebContentsObserver() override;
+
+ bool is_document_loaded_in_main_frame() const {
+ return is_document_loaded_in_main_frame_;
+ }
+
+ void set_main_frame_document_loaded_callback(const base::Closure& callback) {
+ main_frame_document_loaded_callback_ = callback;
+ }
+
+ // content::WebContentsObserver:
+ void DocumentLoadedInFrame(
+ content::RenderFrameHost* render_frame_host) override;
+ void DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) override;
+ void RenderProcessGone(base::TerminationStatus status) override;
+
+ private:
+ explicit OfflinePageWebContentsObserver(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<OfflinePageWebContentsObserver>;
+
+ // Removes the observer and clears the WebContents member.
+ void CleanUp();
+
+ // Tracks whether the document of main frame has been loaded.
+ bool is_document_loaded_in_main_frame_;
+
+ base::Closure main_frame_document_loaded_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(OfflinePageWebContentsObserver);
+};
+
+} // namespace offline_pages
+
+#endif // CHROME_BROWSER_ANDROID_OFFLINE_PAGES_OFFLINE_PAGE_WEB_CONTENTS_OBSERVER_H_
diff --git a/chrome/browser/android/offline_pages/offline_page_web_contents_observer_unittest.cc b/chrome/browser/android/offline_pages/offline_page_web_contents_observer_unittest.cc
new file mode 100644
index 0000000..c685088
--- /dev/null
+++ b/chrome/browser/android/offline_pages/offline_page_web_contents_observer_unittest.cc
@@ -0,0 +1,235 @@
+// Copyright 2015 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 "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
+#include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
+#include "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace offline_pages {
+
+namespace {
+
+const GURL kTestURL("http://example.com/");
+const base::string16 kTestTitle = base::ASCIIToUTF16("Test page title");
+const base::FilePath::CharType kTestFilePath[] = FILE_PATH_LITERAL(
+ "/archive_dir/offline_page.mhtml");
+const int64 kTestFileSize = 123456LL;
+
+class TestMHTMLArchiver : public OfflinePageMHTMLArchiver {
+ public:
+ TestMHTMLArchiver(
+ content::WebContents* web_contents,
+ const GURL& url,
+ const base::string16& title,
+ const base::FilePath& archive_dir);
+ ~TestMHTMLArchiver() override;
+
+ private:
+ void DoGenerateMHTML() override;
+
+ const GURL url_;
+ const base::string16 title_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMHTMLArchiver);
+};
+
+TestMHTMLArchiver::TestMHTMLArchiver(
+ content::WebContents* web_contents,
+ const GURL& url,
+ const base::string16& title,
+ const base::FilePath& archive_dir)
+ : OfflinePageMHTMLArchiver(
+ web_contents, archive_dir, base::ThreadTaskRunnerHandle::Get()),
+ url_(url),
+ title_(title) {
+}
+
+TestMHTMLArchiver::~TestMHTMLArchiver() {
+}
+
+void TestMHTMLArchiver::DoGenerateMHTML() {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&TestMHTMLArchiver::OnGenerateMHTMLDone,
+ base::Unretained(this),
+ url_,
+ title_,
+ kTestFileSize));
+}
+
+} // namespace
+
+class OfflinePageWebContentsObserverTest :
+ public ChromeRenderViewHostTestHarness {
+ public:
+ OfflinePageWebContentsObserverTest();
+ ~OfflinePageWebContentsObserverTest() override;
+
+ void SetUp() override;
+ void TearDown() override;
+
+ // Helper to create an archiver and call its CreateArchive.
+ void CreateArchive(const GURL& url, const base::string16& title);
+
+ // Test tooling methods.
+ void PumpLoop();
+
+ OfflinePageWebContentsObserver* web_contents_observer() const {
+ return web_contents_observer_;
+ }
+
+ OfflinePageArchiver::ArchiverResult last_result() const {
+ return last_result_;
+ }
+
+ private:
+ void OnCreateArchiveDone(OfflinePageArchiver* archiver,
+ OfflinePageArchiver::ArchiverResult result,
+ const GURL& url,
+ const base::string16& title,
+ const base::FilePath& file_path,
+ int64 file_size);
+
+ OfflinePageWebContentsObserver* web_contents_observer_; // Not owned.
+ scoped_ptr<TestMHTMLArchiver> archiver_;
+ OfflinePageArchiver::ArchiverResult last_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(OfflinePageWebContentsObserverTest);
+};
+
+OfflinePageWebContentsObserverTest::OfflinePageWebContentsObserverTest()
+ : last_result_(OfflinePageArchiver::ArchiverResult::
+ ERROR_ARCHIVE_CREATION_FAILED) {
+}
+
+OfflinePageWebContentsObserverTest::~OfflinePageWebContentsObserverTest() {
+}
+
+void OfflinePageWebContentsObserverTest::SetUp() {
+ content::RenderViewHostTestHarness::SetUp();
+ OfflinePageWebContentsObserver::CreateForWebContents(web_contents());
+ web_contents_observer_ =
+ OfflinePageWebContentsObserver::FromWebContents(web_contents());
+ ASSERT_FALSE(web_contents_observer_->is_document_loaded_in_main_frame());
+}
+
+void OfflinePageWebContentsObserverTest::TearDown() {
+ archiver_.reset();
+ content::RenderViewHostTestHarness::TearDown();
+}
+
+void OfflinePageWebContentsObserverTest::CreateArchive(
+ const GURL& url,
+ const base::string16& title) {
+ archiver_.reset(new TestMHTMLArchiver(
+ web_contents(), url, title, base::FilePath(kTestFilePath)));
+ archiver_->CreateArchive(
+ base::Bind(&OfflinePageWebContentsObserverTest::OnCreateArchiveDone,
+ base::Unretained(this)));
+}
+
+void OfflinePageWebContentsObserverTest::OnCreateArchiveDone(
+ OfflinePageArchiver* archiver,
+ OfflinePageArchiver::ArchiverResult result,
+ const GURL& url,
+ const base::string16& title,
+ const base::FilePath& file_path,
+ int64 file_size) {
+ last_result_ = result;
+}
+
+void OfflinePageWebContentsObserverTest::PumpLoop() {
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(OfflinePageWebContentsObserverTest, LoadMainFrameBeforeCreateArchive) {
+ // Navigate in main frame. Document was not loaded yet.
+ content::LoadCommittedDetails details = content::LoadCommittedDetails();
+ details.is_main_frame = true;
+ details.is_in_page = false;
+ content::FrameNavigateParams params = content::FrameNavigateParams();
+ web_contents_observer()->DidNavigateMainFrame(details, params);
+ ASSERT_FALSE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Load document in main frame.
+ web_contents_observer()->DocumentLoadedInFrame(main_rfh());
+ ASSERT_TRUE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Create an archive.
+ CreateArchive(kTestURL, kTestTitle);
+
+ PumpLoop();
+ EXPECT_EQ(OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
+ last_result());
+}
+
+TEST_F(OfflinePageWebContentsObserverTest, LoadMainFrameAfterCreateArchive) {
+ // Navigate in main frame. Document was not loaded yet.
+ content::LoadCommittedDetails details = content::LoadCommittedDetails();
+ details.is_main_frame = true;
+ details.is_in_page = false;
+ content::FrameNavigateParams params = content::FrameNavigateParams();
+ web_contents_observer()->DidNavigateMainFrame(details, params);
+ ASSERT_FALSE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Create an archive. Waiting for document loaded in main frame.
+ CreateArchive(kTestURL, kTestTitle);
+
+ PumpLoop();
+ EXPECT_NE(OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
+ last_result());
+
+ // Load document in main frame.
+ web_contents_observer()->DocumentLoadedInFrame(main_rfh());
+ ASSERT_TRUE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ PumpLoop();
+ EXPECT_EQ(OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
+ last_result());
+}
+
+TEST_F(OfflinePageWebContentsObserverTest, ResetOnPageNavigation) {
+ // Navigate in main frame. Document was not loaded yet.
+ content::LoadCommittedDetails details = content::LoadCommittedDetails();
+ details.is_main_frame = true;
+ details.is_in_page = false;
+ content::FrameNavigateParams params = content::FrameNavigateParams();
+ web_contents_observer()->DidNavigateMainFrame(details, params);
+ ASSERT_FALSE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Load document in main frame.
+ web_contents_observer()->DocumentLoadedInFrame(main_rfh());
+ ASSERT_TRUE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Another navigation should result in waiting for a page load.
+ web_contents_observer()->DidNavigateMainFrame(details, params);
+ ASSERT_FALSE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ // Create an archive. Waiting for document loaded in main frame.
+ CreateArchive(kTestURL, kTestTitle);
+
+ PumpLoop();
+ EXPECT_NE(OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
+ last_result());
+
+ // Load document in main frame.
+ web_contents_observer()->DocumentLoadedInFrame(main_rfh());
+ ASSERT_TRUE(web_contents_observer()->is_document_loaded_in_main_frame());
+
+ PumpLoop();
+ EXPECT_EQ(OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED,
+ last_result());
+}
+
+} // namespace offline_pages
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index c5e09f0..2d57807 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -48,6 +48,7 @@
#include "content/public/browser/web_contents.h"
#if defined(OS_ANDROID)
+#include "chrome/browser/android/offline_pages/offline_page_web_contents_observer.h"
#include "chrome/browser/android/voice_search_tab_helper.h"
#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h"
#include "chrome/browser/ui/android/context_menu_helper.h"
@@ -175,6 +176,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) {
#if defined(OS_ANDROID)
ContextMenuHelper::CreateForWebContents(web_contents);
+ offline_pages::OfflinePageWebContentsObserver::CreateForWebContents(
+ web_contents);
SingleTabModeTabHelper::CreateForWebContents(web_contents);
VoiceSearchTabHelper::CreateForWebContents(web_contents);
WindowAndroidHelper::CreateForWebContents(web_contents);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4bc0c3a..2364f2a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1366,6 +1366,8 @@
'browser/android/offline_pages/offline_page_mhtml_archiver.h',
'browser/android/offline_pages/offline_page_model_factory.cc',
'browser/android/offline_pages/offline_page_model_factory.h',
+ 'browser/android/offline_pages/offline_page_web_contents_observer.cc',
+ 'browser/android/offline_pages/offline_page_web_contents_observer.h',
],
'chrome_browser_browser_process_sources': [
'browser/browser_process.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index edd9868..6146688 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1643,6 +1643,7 @@
# Sources for Offline pages. For now only for Android.
'chrome_unit_tests_offline_pages_sources': [
'browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc',
+ 'browser/android/offline_pages/offline_page_web_contents_observer_unittest.cc',
],
},
'targets': [