diff options
Diffstat (limited to 'chrome/browser/extensions')
4 files changed, 212 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 63791ab..74341d0 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -39,6 +39,7 @@ #include "chrome/browser/extensions/extension_processes_api.h" #include "chrome/browser/extensions/extension_proxy_api.h" #include "chrome/browser/extensions/extension_rlz_module.h" +#include "chrome/browser/extensions/extension_save_page_api.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_settings_api.h" #include "chrome/browser/extensions/extension_sidebar_api.h" @@ -448,6 +449,9 @@ void FactoryRegistry::ResetFunctions() { RegisterFunction<DownloadsAcceptDangerFunction>(); RegisterFunction<DownloadsShowFunction>(); RegisterFunction<DownloadsDragFunction>(); + + // SavePage + RegisterFunction<SavePageAsMHTMLFunction>(); } void FactoryRegistry::GetAllNames(std::vector<std::string>* names) { 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() +} diff --git a/chrome/browser/extensions/extension_save_page_api.h b/chrome/browser/extensions/extension_save_page_api.h new file mode 100644 index 0000000..9de3f1b --- /dev/null +++ b/chrome/browser/extensions/extension_save_page_api.h @@ -0,0 +1,45 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_SAVE_PAGE_API_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SAVE_PAGE_API_H_ + +#include <string> + +#include "chrome/browser/extensions/extension_function.h" +#include "content/browser/tab_contents/tab_contents_observer.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" + +class SavePageAsMHTMLFunction : public AsyncExtensionFunction, + public NotificationObserver { + public: + SavePageAsMHTMLFunction(); + + private: + virtual ~SavePageAsMHTMLFunction(); + + virtual bool RunImpl() OVERRIDE; + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; + + // Called on the file thread. + void CreateTemporaryFile(); + + // Called on the UI thread. + void TemporaryFileCreated(bool success); + void ReturnFailure(const std::string& error); + void ReturnSuccess(int64 file_size); + + int tab_id_; + + // The path to the temporary file containing the MHTML data. + FilePath mhtml_path_; + + NotificationRegistrar registrar_; + DECLARE_EXTENSION_FUNCTION_NAME("experimental.savePage.saveAsMHTML") +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SAVE_PAGE_API_H_ diff --git a/chrome/browser/extensions/extension_save_page_apitest.cc b/chrome/browser/extensions/extension_save_page_apitest.cc new file mode 100644 index 0000000..489ccf6 --- /dev/null +++ b/chrome/browser/extensions/extension_save_page_apitest.cc @@ -0,0 +1,30 @@ +// 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 "base/base_switches.h" +#include "base/command_line.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/common/chrome_switches.h" +#include "net/base/mock_host_resolver.h" + +class ExtensionSavePageApiTest : public ExtensionApiTest { + public: + // TODO(jcivelli): remove this once save-page APIs are no longer experimental. + virtual void SetUpCommandLine(CommandLine* command_line) { + ExtensionApiTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis); + } + + virtual void SetUpInProcessBrowserTestFixture() { + ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + + host_resolver()->AddRule("www.a.com", "127.0.0.1"); + + ASSERT_TRUE(StartTestServer()); + } +}; + +IN_PROC_BROWSER_TEST_F(ExtensionSavePageApiTest, SavePageAsMHTML) { + ASSERT_TRUE(RunExtensionTest("save_page")) << message_; +} |