summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_save_page_api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_save_page_api.cc')
-rw-r--r--chrome/browser/extensions/extension_save_page_api.cc133
1 files changed, 133 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_save_page_api.cc b/chrome/browser/extensions/extension_save_page_api.cc
new file mode 100644
index 0000000..2aee2ce
--- /dev/null
+++ b/chrome/browser/extensions/extension_save_page_api.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2011 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/extensions/extension_save_page_api.h"
+
+#include "base/file_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "content/browser/child_process_security_policy.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/download/mhtml_generation_manager.h"
+#include "content/common/content_notification_types.h"
+#include "content/common/notification_service.h"
+
+// Error messages.
+const char* const kFileTooBigError = "The MHTML file generated is too big.";
+const char* const kMHTMLGenerationFailedError = "Failed to generate MHTML.";
+const char* const kSizeRetrievalError =
+ "Failed to retrieve size of generated MHTML.";
+const char* const kTemporaryFileError = "Failed to create a temporary file.";
+const char* const kTabClosedError = "Cannot find the tab for thie request.";
+
+SavePageAsMHTMLFunction::SavePageAsMHTMLFunction() : tab_id_(0) {
+}
+
+SavePageAsMHTMLFunction::~SavePageAsMHTMLFunction() {
+}
+
+bool SavePageAsMHTMLFunction::RunImpl() {
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id_));
+
+ AddRef(); // Balanced in ReturnFailure/ReturnSuccess()
+
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &SavePageAsMHTMLFunction::CreateTemporaryFile));
+ return true;
+}
+
+void SavePageAsMHTMLFunction::CreateTemporaryFile() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ // TODO(jcivelli): http://crbug.com/97489 we don't clean-up the temporary file
+ // at this point. It must be done before we can take that API
+ // out of experimental.
+ bool success = file_util::CreateTemporaryFile(&mhtml_path_);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &SavePageAsMHTMLFunction::TemporaryFileCreated,
+ success));
+}
+
+void SavePageAsMHTMLFunction::TemporaryFileCreated(bool success) {
+ if (!success) {
+ ReturnFailure(kTemporaryFileError);
+ return;
+ }
+
+ Browser* browser = NULL;
+ TabContentsWrapper* tab_contents_wrapper = NULL;
+
+ if (!ExtensionTabUtil::GetTabById(tab_id_, profile(), include_incognito(),
+ &browser, NULL, &tab_contents_wrapper, NULL)) {
+ ReturnFailure(kTabClosedError);
+ return;
+ }
+
+ TabContents* tab_contents = tab_contents_wrapper->tab_contents();
+ registrar_.Add(this, content::NOTIFICATION_MHTML_GENERATED,
+ Source<RenderViewHost>(tab_contents->render_view_host()));
+ // TODO(jcivelli): we should listen for navigation in the tab, tab closed,
+ // renderer died.
+ g_browser_process->mhtml_generation_manager()->GenerateMHTML(
+ tab_contents, mhtml_path_);
+}
+
+void SavePageAsMHTMLFunction::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == content::NOTIFICATION_MHTML_GENERATED);
+
+ const MHTMLGenerationManager::NotificationDetails* save_details =
+ Details<MHTMLGenerationManager::NotificationDetails>(details).ptr();
+
+ if (mhtml_path_ != save_details->file_path) {
+ // This could happen if there are concurrent MHTML generations going on for
+ // the same tab.
+ LOG(WARNING) << "Received a notification that MHTML was generated but for a"
+ " different file.";
+ return;
+ }
+
+ registrar_.RemoveAll();
+
+ if (save_details->file_size <= 0) {
+ ReturnFailure(kMHTMLGenerationFailedError);
+ return;
+ }
+
+ if (save_details->file_size > std::numeric_limits<int>::max()) {
+ ReturnFailure(kFileTooBigError);
+ return;
+ }
+
+ ReturnSuccess(save_details->file_size);
+}
+
+void SavePageAsMHTMLFunction::ReturnFailure(const std::string& error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ error_ = error;
+
+ SendResponse(false);
+
+ Release(); // Balanced in Run()
+}
+
+void SavePageAsMHTMLFunction::ReturnSuccess(int64 file_size) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ int child_id = render_view_host()->process()->id();
+ ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
+ child_id, mhtml_path_);
+
+ DictionaryValue* dict = new DictionaryValue();
+ result_.reset(dict);
+ dict->SetString("mhtmlFilePath", mhtml_path_.value());
+ dict->SetInteger("mhtmlFileLength", file_size);
+
+ SendResponse(true);
+
+ Release(); // Balanced in Run()
+}