Index: headless/lib/headless_browser_impl.cc |
diff --git a/headless/lib/headless_browser_impl.cc b/headless/lib/headless_browser_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..448bf1a8e65320217a3b06f0500cea1a8cc0131d |
--- /dev/null |
+++ b/headless/lib/headless_browser_impl.cc |
@@ -0,0 +1,214 @@ |
+// 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 "headless/lib/headless_browser_impl.h" |
+ |
+#include "content/public/app/content_main.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/tracing_controller.h" |
+#include "content/public/browser/web_contents.h" |
+#include "headless/lib/browser/headless_browser_context.h" |
+#include "headless/lib/browser/headless_browser_main_parts.h" |
+#include "headless/lib/headless_shell_main_delegate.h" |
+#include "headless/lib/web_contents_impl.h" |
+#include "net/url_request/url_request_context_getter.h" |
+#include "third_party/WebKit/public/platform/Platform.h" |
+#include "third_party/WebKit/public/platform/WebTaskRunner.h" |
+#include "third_party/WebKit/public/platform/WebThread.h" |
+#include "third_party/WebKit/public/platform/WebTraceLocation.h" |
+#include "ui/gfx/geometry/size.h" |
+ |
+namespace headless { |
+ |
+namespace { |
+ |
+class RendererThreadTaskRunner : public base::SingleThreadTaskRunner { |
+ public: |
+ RendererThreadTaskRunner() {} |
+ |
+ bool PostDelayedTask(const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) override { |
+ blink::Platform::current()->mainThread()->taskRunner()->postDelayedTask( |
+ BLINK_FROM_HERE, new Task(task), delay.InMillisecondsF()); |
+ return true; |
+ } |
+ |
+ bool RunsTasksOnCurrentThread() const override { return false; } |
+ |
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) override { |
+ return PostDelayedTask(from_here, task, delay); |
+ } |
+ |
+ private: |
+ ~RendererThreadTaskRunner() override {} |
+ |
+ class Task : public blink::WebTaskRunner::Task { |
+ public: |
+ Task(const base::Closure& function_to_run) |
+ : function_to_run_(function_to_run){}; |
+ |
+ void run() override { function_to_run_.Run(); } |
+ |
+ private: |
+ base::Closure function_to_run_; |
+ }; |
+}; |
+ |
+class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner { |
+ public: |
+ BrowserThreadTaskRunner(content::BrowserThread::ID thread_id) |
+ : thread_id_(thread_id) {} |
+ |
+ bool PostDelayedTask(const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) override { |
+ return content::BrowserThread::PostDelayedTask(thread_id_, from_here, task, |
+ delay); |
+ } |
+ |
+ bool RunsTasksOnCurrentThread() const override { return false; } |
+ |
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) override { |
+ return content::BrowserThread::PostNonNestableDelayedTask( |
+ thread_id_, from_here, task, delay); |
+ } |
+ |
+ private: |
+ ~BrowserThreadTaskRunner() override {} |
+ content::BrowserThread::ID thread_id_; |
+}; |
+} |
+ |
+HeadlessBrowserImpl::HeadlessBrowserImpl() |
+ : browser_main_thread_( |
+ new BrowserThreadTaskRunner(content::BrowserThread::UI)) |
+ , renderer_main_thread_(new RendererThreadTaskRunner()) |
+ , is_writing_trace_(false) {} |
+ |
+HeadlessBrowserImpl::~HeadlessBrowserImpl() {} |
+ |
+/*static*/ HeadlessBrowserImpl* HeadlessBrowserImpl::Get() { |
+ static HeadlessBrowserImpl* browser = new HeadlessBrowserImpl(); |
+ return browser; |
+} |
+ |
+/*static*/ HeadlessBrowser* HeadlessBrowser::Get() { |
+ return HeadlessBrowserImpl::Get(); |
+} |
+ |
+scoped_ptr<WebContents> HeadlessBrowserImpl::CreateWebContents( |
+ const gfx::Size& size) { |
+ WebContentsImpl* web_contents = |
+ new WebContentsImpl(browser_context(), size); |
+ return scoped_ptr<WebContents>(web_contents); |
+} |
+ |
+scoped_refptr<base::SingleThreadTaskRunner> |
+HeadlessBrowserImpl::browser_main_thread() { |
+ return browser_main_thread_; |
+} |
+ |
+scoped_refptr<base::SingleThreadTaskRunner> |
+HeadlessBrowserImpl::renderer_main_thread() { |
+ return renderer_main_thread_; |
+} |
+ |
+int HeadlessBrowserImpl::Run( |
+ const Options& options, |
+ const base::Closure& on_browser_start_callback) |
+{ |
+ on_start_callback_ = make_scoped_ptr( |
+ new base::Closure(on_browser_start_callback)); |
+ |
+ headless::HeadlessShellMainDelegate delegate(this); |
+ content::ContentMainParams params(&delegate); |
+ params.argc = options.argc; |
+ params.argv = options.argv; |
+ return content::ContentMain(params); |
+} |
+ |
+void HeadlessBrowserImpl::Stop() { |
+ PostShutdownTask(); |
+} |
+ |
+void HeadlessBrowserImpl::StartTracing( |
+ const base::trace_event::TraceConfig& trace_config, |
+ const base::Closure& tracing_started_callback) |
+{ |
+ content::TracingController::GetInstance()->StartTracing( |
+ trace_config, |
+ tracing_started_callback); |
+} |
+ |
+void HeadlessBrowserImpl::StopTracing( |
+ const std::string& log_file_name, |
+ const base::Closure& tracing_stopped_callback) |
+{ |
+ { |
+ base::AutoLock lock(is_writing_trace_lock_); |
+ is_writing_trace_ = true; |
+ } |
+ content::TracingController::GetInstance()->StopTracing( |
+ content::TracingController::CreateFileSink( |
+ base::FilePath(log_file_name), |
+ base::Bind(&HeadlessBrowserImpl::DidFinishWritingTrace, |
+ base::Unretained(this), |
+ tracing_stopped_callback))); |
+} |
+ |
+void HeadlessBrowserImpl::DidFinishWritingTrace( |
+ const base::Closure& tracing_stopped_callback) |
+{ |
+ { |
+ base::AutoLock lock(is_writing_trace_lock_); |
+ is_writing_trace_ = false; |
+ } |
+ tracing_stopped_callback.Run(); |
+} |
+ |
+HeadlessBrowserContext* HeadlessBrowserImpl::browser_context() { |
+ DCHECK(browser_main_parts()); |
+ return browser_main_parts()->browser_context(); |
+} |
+ |
+HeadlessBrowserMainParts* HeadlessBrowserImpl::browser_main_parts() { |
+ return browser_main_parts_; |
+} |
+ |
+void HeadlessBrowserImpl::set_browser_main_parts( |
+ HeadlessBrowserMainParts* browser_main_parts) { |
+ browser_main_parts_ = browser_main_parts; |
+} |
+ |
+void HeadlessBrowserImpl::RunOnStartCallback() { |
+ DCHECK(on_start_callback_); |
+ on_start_callback_->Run(); |
+} |
+ |
+void HeadlessBrowserImpl::Shutdown() { |
+ { |
+ base::AutoLock lock(is_writing_trace_lock_); |
+ DCHECK(!is_writing_trace_); |
+ } |
+ |
+ for (const auto& web_contents : web_contents_) { |
+ web_contents->web_contents()->Close(); |
+ } |
+ web_contents_.clear(); |
+ browser_main_thread()->PostTask(FROM_HERE, |
+ base::MessageLoop::QuitWhenIdleClosure()); |
+} |
+ |
+void HeadlessBrowserImpl::PostShutdownTask() { |
+ browser_main_thread()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&HeadlessBrowserImpl::Shutdown, base::Unretained(this))); |
+} |
+ |
+} // namespace headless |