embedded_browser.cpp 3.76 KB
#include "stdafx.h"

#include "etradeclient/browser/embedded_browser.h"

#include <mutex>
#include <condition_variable>

#include "include/cef_request.h"
#include "include/cef_cookie.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_closure_task.h"

namespace
{
	class SetCookieProxy : public CefSetCookieCallback
	{
	public:
		SetCookieProxy(std::mutex& mtx, std::condition_variable& cv) : 
			m_mtx(mtx), m_cv(cv), m_set_cookie_done(false), m_set_cookie_res(false)
		{}

		void SetCookie(const std::string& url, const CefCookie& cookie)
		{
			CEF_REQUIRE_IO_THREAD();
			CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
			if (!manager->SetCookie(url, cookie, CefRefPtr<CefSetCookieCallback>(this)))
			{
				m_set_cookie_res = false; // Set cookie failed.
				m_set_cookie_done = true;
				m_cv.notify_one(); // Notify the other thread when setting cookie failed.
			}
		}
		void OnComplete(bool res)
		{
			CEF_REQUIRE_IO_THREAD();
			{
				std::lock_guard<std::mutex> lg(m_mtx);
				m_set_cookie_res = res;
				m_set_cookie_done = true;
			}
			m_cv.notify_one();
		}
	private:
		std::mutex&					m_mtx;
		std::condition_variable&	m_cv;
		bool 						m_set_cookie_done;
		bool 						m_set_cookie_res;
	private:
		friend class EmbeddedBrower;

		IMPLEMENT_REFCOUNTING(SetCookieProxy);
		DISALLOW_COPY_AND_ASSIGN(SetCookieProxy);
	};
}


bool EmbeddedBrower::SetCookie(const std::string& url, const CefCookie& cookie)
{
	std::mutex mtx;
	std::condition_variable cv;
	CefRefPtr<SetCookieProxy> set_cookie_proxy = new SetCookieProxy(mtx, cv);
	CefPostTask(TID_IO, base::Bind(&SetCookieProxy::SetCookie, set_cookie_proxy, url, cookie));

	std::unique_lock<std::mutex> lk(mtx);
	cv.wait(lk, [&]
	{
		return set_cookie_proxy->m_set_cookie_done;
	});
	return set_cookie_proxy->m_set_cookie_res;
}


EmbeddedBrower::EmbeddedBrower() : m_cef_browser(nullptr)
{}
EmbeddedBrower::~EmbeddedBrower()
{
	if (m_cef_browser) // release browser if still active
		m_cef_browser = nullptr;
}

void EmbeddedBrower::AttachCEFBrowser(CefRefPtr<CefBrowser> cef_browser)
{
	m_cef_browser = cef_browser;
}
void EmbeddedBrower::DetachCEFBrowser(CefRefPtr<CefBrowser> cef_browser)
{
	if (nullptr != m_cef_browser && m_cef_browser->IsSame(cef_browser))
		m_cef_browser = nullptr; // Release reference of browser instance.
}
bool EmbeddedBrower::CEFBrowserAttached() const
{
	return (nullptr != m_cef_browser);
}

void EmbeddedBrower::Close(bool force_close)
{
	// Notify the browser window that we would like to close it. This
	// will result in a call to MainViewBrowserHandler::DoClose() if the
	// JavaScript 'onbeforeunload' event handler allows it.
	m_cef_browser->GetHost()->CloseBrowser(force_close);
}
void EmbeddedBrower::Resize(const RECT& rect)
{
	// cef stretch to to full view
	CefWindowHandle hwnd = m_cef_browser->GetHost()->GetWindowHandle();
	if (hwnd)
	{
		HDWP hdwp = BeginDeferWindowPos(1);
		hdwp = DeferWindowPos(hdwp, hwnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
		EndDeferWindowPos(hdwp);
	}
}

void EmbeddedBrower::Copy()
{
	m_cef_browser->GetMainFrame()->Copy();
}
void EmbeddedBrower::Cut()
{
	m_cef_browser->GetMainFrame()->Cut();
}
void EmbeddedBrower::Paste()
{
	m_cef_browser->GetMainFrame()->Paste();
}

void EmbeddedBrower::NavigateTo(const std::string& url) const
{
	m_cef_browser->GetMainFrame()->LoadURL(url);
}
void EmbeddedBrower::LoadRequest(const CefRefPtr<CefRequest>& req) const
{
	m_cef_browser->GetMainFrame()->LoadRequest(req);
}

void EmbeddedBrower::GoBack() const
{
	m_cef_browser->GoBack();
}

void EmbeddedBrower::GoForward() const
{
	m_cef_browser->GoForward();
}

void EmbeddedBrower::Reload() const
{
	m_cef_browser->Reload();
}

void EmbeddedBrower::SetFocus(bool focus)
{
	m_cef_browser->GetHost()->SetFocus(true);
}