- Code: Select all
class CaseWareCefApp : public CefApp, public CefRenderProcessHandler
{
public:
CaseWareCefApp()
: m_ReturnValue()
, m_DefaultDocument(nullptr)
, m_ReturnValueResult(S_OK)
, m_HasReturned(false)
{
}
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message) OVERRIDE;
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE
{
return this;
}
private:
virtual void OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
virtual void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
VARIANT m_ReturnValue;
CCVDocument* m_DefaultDocument;
HRESULT m_ReturnValueResult;
bool m_HasReturned;
public:
const VARIANT* GetReturnValue() const { return m_HasReturned ? &m_ReturnValue : nullptr; }
void SetDefaultDocument(CCVDocument* document) { m_DefaultDocument = document; }
HRESULT GetReturnValueResult() const { return m_ReturnValueResult; }
IMPLEMENT_REFCOUNTING(CaseWareCefApp);
};
- Code: Select all
bool CaseWareCefApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
{
if (message->GetName() == _T("Return Value"))
{
OnContextReleased(browser, browser->GetMainFrame(), browser->GetMainFrame()->GetV8Context());
return true;
}
return false;
}
void CaseWareCefApp::OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar)
{
registrar->AddCustomScheme(BUILDSCHEME, false, false, false);
registrar->AddCustomScheme(BUILDCEFSCHEME, true, true, false);
}
void CaseWareCefApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
// Do something with context. Never gets here.
}
- Code: Select all
CefRefPtr<CefApp> InitializeCEF()
{
if (AfxGetApp() && AfxGetApp()->m_nThreadID == GetCurrentThreadId()) {
if (!gCEFChecked) {
gCEFChecked = TRUE;
if (gUseCEF && CEFDLLAvailable()) {
CefSettings settings;
CefMainArgs args;
CefRefPtr<CefApp> app = new CaseWareCefApp;
settings.multi_threaded_message_loop = true;
settings.pack_loading_disabled = false;
#ifdef DEBUG
settings.ignore_certificate_errors = true;
#endif
settings.no_sandbox = true;
wchar_t exeName[_MAX_PATH];
GetModuleFileNameW(::AfxGetInstanceHandle(),exeName,_countof(exeName));
wchar_t exePath[_MAX_PATH];
SplitPathW(exeName, exePath, NULL, NULL);
wcscat(exePath, L"cwcef.exe");
CefString(&settings.browser_subprocess_path) = exePath;
wchar_t tempPath[_MAX_PATH];
GetTempPathW(_countof(tempPath), tempPath);
wcscat(tempPath, L"CaseWare_CEF");
CreateDirectoryW(tempPath, NULL);
CefString(&settings.cache_path) = tempPath;
wcscat(tempPath, L"\\debug.log");
CefString(&settings.log_file) = tempPath;
CStringW proglanguageCode;
proglanguageCode.LoadString(IDS_LANGUAGE_CODE);
CefString(&settings.locale) = proglanguageCode;
wchar_t lpszProduct[128] = L"";
swprintf(lpszProduct, L"CaseWare/%s/%s Chrome/47.0.2526.80", CWorTB(L"WP", L"Time"), (LPCWSTR) CT2CW(GetAppShortVersionString()));
CefString(&settings.product_version) = lpszProduct;
args.instance = AfxGetInstanceHandle();
CefInitialize(args, settings, app, nullptr);
CefRegisterSchemeHandlerFactory(BUILDSCHEME, "", new CaseWareSchemeHandlerFactory());
CefRegisterSchemeHandlerFactory(BUILDCEFSCHEME, "", new CaseWareSchemeHandlerFactory());
CefRegisterSchemeHandlerFactory("http", BUILDCEFSCHEME, new CaseWareSchemeHandlerFactory());
CefRegisterSchemeHandlerFactory("https", BUILDCEFSCHEME, new CaseWareSchemeHandlerFactory());
return app;
}
}
}
return nullptr;
}
- Code: Select all
class CCefSimpleView;
class CCefSimpleHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefKeyboardHandler
{
public:
CCefSimpleHandler();
~CCefSimpleHandler();
// Provide access to the single global instance of this object.
static CCefSimpleHandler* GetInstance();
// CefClient methods:
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE {
return this;
}
// CefDisplayHandler methods:
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) OVERRIDE;
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) OVERRIDE;
// CefLifeSpanHandler methods:
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
CefRefPtr< CefFrame > frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr< CefClient >& client,
CefBrowserSettings& settings,
bool* no_javascript_access) OVERRIDE;
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// CefKeyboardHandler methods.
virtual bool OnKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event) OVERRIDE;
// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);
bool IsClosing() const { return is_closing_; }
void SetIsModal(bool isModal) { m_IsModal = isModal; }
CCefSimpleView* GetView() const { return m_View; }
void SetView(CCefSimpleView* view);
CefRefPtr<CefBrowser> GetBrowser() { return browser_list_.back(); }
void ShowDevTools(CefRefPtr<CefBrowser> browser);
CString GetUrl() const { return m_Url; }
void SetUrl(const CString& url) { m_Url = url; }
void SetParent(CWnd* parent) { m_Parent = parent; }
bool GetIsFixedSize() const { return m_IsFixedSize; }
void SetIsFixedSize(bool isFixedSize) { m_IsFixedSize = isFixedSize; }
private:
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
BrowserList browser_list_;
bool is_closing_;
bool m_IsModal;
CCefSimpleView* m_View;
CCriticalSection m_ViewLock;
CString m_Url;
HANDLE m_hAccel;
DWORD m_nAccelCount;
CWnd* m_Parent;
bool m_IsFixedSize;
CString m_ErrorMessage;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(CCefSimpleHandler);
};
class CCefSimpleView : public CMutableFrame
{
public:
CCefSimpleView() : CMutableFrame()
{
m_pHandler = nullptr;
}
virtual ~CCefSimpleView();
static LPCTSTR GetAfxName()
{
if (s_AfxName == nullptr)
{
s_AfxName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
}
return s_AfxName;
}
static LPCTSTR s_AfxName;
CString GetUrl() const { if (m_pHandler) return m_pHandler->GetUrl(); else return _T(""); }
afx_msg void OnSetFocus( CWnd* oldWindow );
afx_msg LRESULT OnBrowserCreated(WPARAM, LPARAM);
afx_msg void OnSyncDetails();
DECLARE_DYNCREATE(CCefSimpleView)
CCefSimpleHandler* m_pHandler;
DECLARE_MESSAGE_MAP()
};
- Code: Select all
CCefSimpleHandler::CCefSimpleHandler()
: is_closing_(false)
, m_IsModal(true)
, m_View(nullptr)
, m_ViewLock()
, m_Url()
, m_hAccel(nullptr)
, m_nAccelCount(0)
, m_Parent(nullptr)
, m_IsFixedSize(false)
, m_ErrorMessage()
{
m_ErrorMessage.LoadString(IDS_CEF_LOAD_ERROR_MSG);
}
CCefSimpleHandler::~CCefSimpleHandler()
{
}
// static
CCefSimpleHandler* CCefSimpleHandler::GetInstance()
{
return new CCefSimpleHandler;
}
bool CCefSimpleHandler::OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
CefRefPtr< CefFrame > frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr< CefClient >& client,
CefBrowserSettings& settings,
bool* no_javascript_access)
{
CEF_REQUIRE_UI_THREAD();
client = new CCefSimpleHandler();
windowInfo.style &= ~WS_VISIBLE;
return true;
}
void CCefSimpleHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CEF_REQUIRE_UI_THREAD();
m_Parent->SendMessage(WMA_CEF_BROWSER_CREATED, (WPARAM)this, (LPARAM)browser.get());
if (m_View != nullptr)
{
m_View->PostMessage(WMA_CEF_BROWSER_CREATED, 0, 0);
}
// Add to the list of existing browsers.
browser_list_.push_back(browser);
}
bool CCefSimpleHandler::DoClose(CefRefPtr<CefBrowser> browser)
{
CEF_REQUIRE_UI_THREAD();
// Closing the main window requires special handling. See the DoClose()
// documentation in the CEF header for a detailed destription of this
// process.
if (browser_list_.size() == 1) {
// Set a flag to indicate that the window close should be allowed.
is_closing_ = true;
}
// Allow the close. For windowed browsers this will result in the OS close
// event being sent.
return false;
}
void CCefSimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(_T("Return Value"));
browser->SendProcessMessage(PID_RENDERER, message); // Gets here, but never gets to OnProcessMessageReceived
if (m_Parent != nullptr)
{
m_Parent->SendMessage(WMA_CEF_BROWSER_DESTROYED, (WPARAM)this, (LPARAM)browser.get());
}
// Remove from the list of existing browsers.
BrowserList::iterator bit = browser_list_.begin();
for (; bit != browser_list_.end(); ++bit) {
if ((*bit)->IsSame(browser)) {
browser_list_.erase(bit);
break;
}
}
}
void CCefSimpleHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl)
{
CEF_REQUIRE_UI_THREAD();
// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
return;
// Display a load error message.
CStringW compositeErrorMessage;
CStringW errorMessageW;
errorMessageW = CT2W(m_ErrorMessage);
errorMessageW.Replace(L"%s1", failedUrl.c_str());
errorMessageW.Replace(L"%s2", errorText.c_str());
compositeErrorMessage = L"<html><body bgcolor=\"white\">";
compositeErrorMessage += L"<h2>";
compositeErrorMessage += errorMessageW;
compositeErrorMessage += L" (";
WCHAR errorCodeMessage[10] {0};
compositeErrorMessage += _itow(errorCode, errorCodeMessage, 10);
compositeErrorMessage += L").</h2></body></html>";
frame->LoadString(compositeErrorMessage.GetBuffer(), failedUrl);
}
bool CCefSimpleHandler::OnKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& theEvent,
CefEventHandle os_event)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CEF_REQUIRE_UI_THREAD();
// Handle main application accelerators before passing on events to browser
if (theEvent.type == KEYEVENT_RAWKEYDOWN)
{
WORD cmd = 0;
if (!m_hAccel)
{
HRSRC res = FindResource(CWGetInstanceHandle(), MAKEINTRESOURCE(IDR_BROWSEKEY), RT_ACCELERATOR);
if (res)
{
m_hAccel = LoadResource(CWGetInstanceHandle(), res);
m_nAccelCount = SizeofResource(CWGetInstanceHandle(), res) / 8;
}
}
if (m_hAccel)
{
LPBYTE accelTable = (LPBYTE)LockResource(m_hAccel);
for (DWORD i = 0; i < m_nAccelCount; i++)
{
LPACCEL entry = (LPACCEL)(accelTable + i * 8);
if ((entry->key == theEvent.windows_key_code) && ((entry->fVirt & 0x0b) == 0x0b))
{
cmd = entry->cmd;
}
}
}
else
{
ASSERT(false);
}
if (cmd && m_View != nullptr)
{
if (theEvent.type == KEYEVENT_RAWKEYDOWN) m_View->PostMessage(WM_COMMAND, cmd);
return true;
}
}
return false;
}
void CCefSimpleHandler::CloseAllBrowsers(bool force_close)
{
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI,
base::Bind(&CCefSimpleHandler::CloseAllBrowsers, this, force_close));
return;
}
if (browser_list_.empty())
return;
BrowserList::const_iterator it = browser_list_.begin();
for (; it != browser_list_.end(); ++it)
(*it)->GetHost()->CloseBrowser(force_close);
}
void CCefSimpleHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title)
{
CEF_REQUIRE_UI_THREAD();
CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
SetWindowTextW(hwnd, std::wstring(title).c_str());
}
void CCefSimpleHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CEF_REQUIRE_UI_THREAD();
if (wcscmp(url.c_str(),L"about:blank"))
{
SetUrl(url.c_str());
}
}
void CCefSimpleHandler::SetView(CCefSimpleView* view)
{
m_ViewLock.Lock();
m_View = view;
if (m_View) m_View->m_pHandler = this;
m_ViewLock.Unlock();
}
void CCefSimpleHandler::ShowDevTools(CefRefPtr<CefBrowser> browser)
{
CefWindowInfo windowInfo;
CefBrowserSettings settings;
CefPoint inspectElementAt;
#if defined(OS_WIN)
windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), _T("DevTools"));
#endif
SetUrl(_T("chrome-devtools://devtools/devtools.html"));
browser->GetHost()->ShowDevTools(windowInfo, this, settings, inspectElementAt);
}
///////////////////////////////////////////////////////////////////////
// CCefSimpleView
///////////////////////////////////////////////////////////////////////
LPCTSTR CCefSimpleView::s_AfxName = nullptr;
IMPLEMENT_DYNCREATE(CCefSimpleView, CMutableFrame)
BEGIN_MESSAGE_MAP(CCefSimpleView, CMutableFrame)
ON_COMMAND(ID_OPERATION_DETAILS, OnSyncDetails)
ON_MESSAGE(WMA_CEF_BROWSER_CREATED, OnBrowserCreated)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CCefSimpleView::~CCefSimpleView()
{
}
LRESULT CCefSimpleView::OnBrowserCreated(WPARAM, LPARAM)
{
if (m_pHandler->GetBrowser())
{
CString url = GetURL();
m_pHandler->GetBrowser()->GetMainFrame()->LoadURL((LPCTSTR) ToSchemeSafeURL(url.IsEmpty() ? GetUrl() : url));
}
return 0;
}
void CCefSimpleView::OnSetFocus( CWnd* pOldWnd )
{
__super::OnSetFocus(pOldWnd);
if(m_pHandler && m_pHandler->GetBrowser())
{
// Pass focus to the browser window
if (m_pHandler->GetBrowser()->GetHost()) m_pHandler->GetBrowser()->GetHost()->SetFocus(true);
//::PostMessage(m_pHandler->m_BrowserHwnd, WM_SETFOCUS, (WPARAM) pOldWnd->m_hWnd, NULL);
}
}
void CCefSimpleView::OnSyncDetails()
{
if (m_pHandler)
{
m_pHandler->ShowDevTools(m_pHandler->GetBrowser());
}
}