SIGN IN SIGN UP
cefsharp / CefSharp UNCLAIMED

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework

0 0 121 C#
// Copyright © 2010-2015 The CefSharp Authors. All rights reserved.
2014-03-09 13:49:35 +01:00
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "Stdafx.h"
#include "include/wrapper/cef_stream_resource_handler.h"
2014-03-09 13:49:35 +01:00
#include "ClientAdapter.h"
#include "CefRequestWrapper.h"
#include "CefContextMenuParamsWrapper.h"
#include "CefDragDataWrapper.h"
#include "TypeConversion.h"
#include "CefSharpBrowserWrapper.h"
#include "CefDownloadItemCallbackWrapper.h"
#include "CefBeforeDownloadCallbackWrapper.h"
#include "CefGeolocationCallbackWrapper.h"
#include "CefFileDialogCallbackWrapper.h"
#include "CefAuthCallbackWrapper.h"
#include "CefJSDialogCallbackWrapper.h"
#include "CefRequestCallbackWrapper.h"
#include "WindowInfo.h"
#include "Serialization\Primitives.h"
#include "Serialization\V8Serialization.h"
#include "Serialization\JsObjectsSerialization.h"
#include "Serialization\ObjectsSerialization.h"
#include "Messaging\Messages.h"
using namespace CefSharp::Internals::Messaging;
using namespace CefSharp::Internals::Serialization;
2014-03-09 13:49:35 +01:00
namespace CefSharp
{
namespace Internals
{
IBrowser^ ClientAdapter::GetBrowserWrapper(int browserId, bool isPopup)
{
if (_browserControl->HasParent)
{
return _browserAdapter->GetBrowser();
}
if(isPopup)
{
IBrowser^ browserWrapper;
if (_popupBrowsers->TryGetValue(browserId, browserWrapper))
{
return browserWrapper;
}
auto stackFrame = gcnew StackFrame(1);
auto callingMethodName = stackFrame->GetMethod()->Name;
ThrowUnknownPopupBrowser(gcnew String(L"ClientAdapter::" + callingMethodName));
}
return _browserAdapter->GetBrowser();
}
void ClientAdapter::CloseAllPopups(bool forceClose)
{
if (_popupBrowsers->Count > 0)
{
for each (IBrowser^ browser in _popupBrowsers->Values)
{
browser->GetHost()->CloseBrowser(forceClose);
// NOTE: We don't dispose the IBrowsers here
// because ->CloseBrowser() will invoke
// ->OnBeforeClose() for the browser.
// OnBeforeClose() disposes the IBrowser there.
}
}
}
2014-03-09 13:49:35 +01:00
bool ClientAdapter::OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& target_url,
const CefString& target_frame_name, CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture,
const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo,
2014-03-09 13:49:35 +01:00
CefRefPtr<CefClient>& client, CefBrowserSettings& settings, bool* no_javascript_access)
{
auto handler = _browserControl->LifeSpanHandler;
2015-07-28 17:17:12 +10:00
2014-03-09 13:49:35 +01:00
if (handler == nullptr)
{
return false;
}
2015-07-28 17:17:12 +10:00
IWebBrowser^ newBrowser = nullptr;
bool createdWrapper = false;
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
WindowInfo windowInfoWrapper(&windowInfo);
2015-07-01 13:53:17 +10:00
auto result = handler->OnBeforePopup(
_browserControl, browserWrapper,
2015-06-08 22:48:29 -04:00
%frameWrapper, StringUtils::ToClr(target_url),
StringUtils::ToClr(target_frame_name),
(CefSharp::WindowOpenDisposition)target_disposition,
user_gesture,
2015-07-28 17:17:12 +10:00
%windowInfoWrapper, *no_javascript_access, newBrowser);
2015-05-05 17:31:46 +01:00
if (newBrowser != nullptr)
2015-05-07 23:40:56 +01:00
{
auto newBrowserInternal = dynamic_cast<IWebBrowserInternal^>(newBrowser);
2015-05-05 17:31:46 +01:00
2015-05-08 11:14:29 +01:00
if (newBrowserInternal != nullptr)
2015-05-07 23:40:56 +01:00
{
newBrowserInternal->HasParent = true;
auto renderBrowser = dynamic_cast<IRenderWebBrowser^>(newBrowser);
if (renderBrowser == nullptr)
{
HWND hwnd = (HWND)newBrowserInternal->ControlHandle.ToPointer();
RECT rect;
GetClientRect(hwnd, &rect);
windowInfo.SetAsChild(hwnd, rect);
}
else
2015-05-08 11:14:29 +01:00
{
windowInfo.SetAsWindowless(windowInfo.parent_window, TRUE);
}
2015-05-05 17:31:46 +01:00
auto browserAdapter = dynamic_cast<ManagedCefBrowserAdapter^>(newBrowserInternal->BrowserAdapter);
2015-05-08 11:14:29 +01:00
if (browserAdapter != nullptr)
{
client = browserAdapter->GetClientAdapter().get();
}
}
2015-05-07 23:40:56 +01:00
}
2015-05-05 17:31:46 +01:00
return result;
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
if (browser->IsPopup() && !_browserControl->HasParent)
{
auto browserWrapper = gcnew CefSharpBrowserWrapper(browser);
// Add to the list of popup browsers.
_popupBrowsers->Add(browser->GetIdentifier(), browserWrapper);
auto handler = _browserControl->PopupHandler;
if (handler != nullptr)
{
handler->OnAfterCreated(_browserControl, browserWrapper);
}
}
else
2014-03-09 13:49:35 +01:00
{
_browserHwnd = browser->GetHost()->GetWindowHandle();
_cefBrowser = browser;
if (!Object::ReferenceEquals(_browserAdapter, nullptr))
{
_browserAdapter->OnAfterBrowserCreated(browser->GetIdentifier());
//save callback factory for this browser
//it's only going to be present after browseradapter is initialized
_javascriptCallbackFactories->Add(browser->GetIdentifier(), _browserAdapter->JavascriptCallbackFactory);
//transmit async bound objects
auto jsRootObjectMessage = CefProcessMessage::Create(kJavascriptRootObjectRequest);
auto argList = jsRootObjectMessage->GetArgumentList();
SerializeJsObject(_browserAdapter->JavascriptObjectRepository->AsyncRootObject, argList, 0);
SerializeJsObject(_browserAdapter->JavascriptObjectRepository->RootObject, argList, 1);
browser->SendProcessMessage(CefProcessId::PID_RENDERER, jsRootObjectMessage);
}
2015-05-07 18:32:14 +01:00
auto handler = _browserControl->LifeSpanHandler;
2015-05-07 18:32:14 +01:00
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
2015-05-07 18:32:14 +01:00
handler->OnAfterCreated(_browserControl, browserWrapper);
}
}
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
if (browser->IsPopup() && !_browserControl->HasParent)
{
// Remove from the browser popup list.
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
auto handler = _browserControl->PopupHandler;
if (handler != nullptr)
2015-06-08 22:48:29 -04:00
{
handler->OnBeforeClose(_browserControl, browserWrapper);
2015-06-08 22:48:29 -04:00
}
_popupBrowsers->Remove(browser->GetIdentifier());
// Dispose the CefSharpBrowserWrapper
delete browserWrapper;
}
//TODO: When creating a new ChromiumWebBrowser and passing in a newBrowser to OnBeforePopup
//the handles don't match up (at least in WPF), need to investigate further.
else if (_browserHwnd == browser->GetHost()->GetWindowHandle() || _browserControl->HasParent)
2014-03-09 13:49:35 +01:00
{
auto handler = _browserControl->LifeSpanHandler;
2014-03-09 13:49:35 +01:00
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
handler->OnBeforeClose(_browserControl, browserWrapper);
2014-03-09 13:49:35 +01:00
}
2014-10-07 21:35:57 +02:00
_cefBrowser = NULL;
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnLoadingStateChange(CefRefPtr<CefBrowser> browser, bool isLoading, bool canGoBack, bool canGoForward)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto args = gcnew LoadingStateChangedEventArgs(browserWrapper, canGoBack, canGoForward, isLoading);
if (browser->IsPopup())
{
auto handler = _browserControl->PopupHandler;
if (handler != nullptr)
{
handler->OnLoadingStateChange(_browserControl, args);
}
}
else
{
_browserControl->SetLoadingStateChange(args);
}
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& address)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto args = gcnew AddressChangedEventArgs(StringUtils::ToClr(address));
if (browser->IsPopup())
2014-03-09 13:49:35 +01:00
{
auto handler = _browserControl->PopupHandler;
if (handler != nullptr)
{
handler->OnAddressChanged(_browserControl, args);
}
}
else
{
_browserControl->SetAddress(args);
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title)
{
//TODO: Expand this handling so user has more control
//NOTE: This should probably be changed if as users can now provide their own popup windows
if (browser->IsPopup())
{
// Set the popup window title
auto hwnd = browser->GetHost()->GetWindowHandle();
SetWindowText(hwnd, std::wstring(title).c_str());
}
else
{
auto args = gcnew TitleChangedEventArgs(StringUtils::ToClr(title));
_browserControl->SetTitle(args);
}
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnFaviconURLChange(CefRefPtr<CefBrowser> browser, const std::vector<CefString>& iconUrls)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
popupHandler->OnFaviconUrlChange(_browserControl, browserWrapper, StringUtils::ToClr(iconUrls));
}
}
else
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
handler->OnFaviconUrlChange(_browserControl, browserWrapper, StringUtils::ToClr(iconUrls));
}
}
}
2014-03-09 13:49:35 +01:00
bool ClientAdapter::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text)
{
String^ tooltip = StringUtils::ToClr(text);
2015-06-08 22:48:29 -04:00
// TODO: Deal with popuup browsers properly...
2014-03-09 13:49:35 +01:00
if (tooltip != _tooltip)
{
_tooltip = tooltip;
_browserControl->SetTooltipText(_tooltip);
}
//TODO: Should this be true for WinForms?
2014-03-09 13:49:35 +01:00
return true;
}
bool ClientAdapter::OnConsoleMessage(CefRefPtr<CefBrowser> browser, const CefString& message, const CefString& source, int line)
{
auto args = gcnew ConsoleMessageEventArgs(StringUtils::ToClr(message), StringUtils::ToClr(source), line);
2014-03-09 13:49:35 +01:00
_browserControl->OnConsoleMessage(args);
//TODO: Should this be true? Cancels message being output to console
2014-03-09 13:49:35 +01:00
return true;
}
void ClientAdapter::OnStatusMessage(CefRefPtr<CefBrowser> browser, const CefString& value)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto args = gcnew StatusMessageEventArgs(browserWrapper, StringUtils::ToClr(value));
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
popupHandler->OnStatusMessage(_browserControl, args);
}
}
else
{
_browserControl->OnStatusMessage(args);
}
}
2014-03-09 13:49:35 +01:00
bool ClientAdapter::OnKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent& event, CefEventHandle os_event)
{
if (browser->IsPopup())
2014-03-09 13:49:35 +01:00
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
return popupHandler->OnKeyEvent(
_browserControl, browserWrapper, (KeyType)event.type,
event.windows_key_code, event.native_key_code,
(CefEventFlags)event.modifiers, event.is_system_key == 1);
}
2014-03-09 13:49:35 +01:00
}
else
{
auto handler = _browserControl->KeyboardHandler;
2014-03-09 13:49:35 +01:00
if (handler != nullptr)
2015-06-08 22:48:29 -04:00
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
return handler->OnKeyEvent(
_browserControl, browserWrapper, (KeyType)event.type, event.windows_key_code,
event.native_key_code,
(CefEventFlags)event.modifiers, event.is_system_key == 1);
}
}
2015-06-08 22:48:29 -04:00
return false;
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent& event, CefEventHandle os_event, bool* is_keyboard_shortcut)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
popupHandler->OnPreKeyEvent(_browserControl, browserWrapper, (KeyType)event.type, event.windows_key_code, event.native_key_code, (CefEventFlags)event.modifiers, event.is_system_key == 1, *is_keyboard_shortcut);
}
}
else
{
auto handler = _browserControl->KeyboardHandler;
2015-06-08 22:48:29 -04:00
if (handler != nullptr)
2015-06-08 22:48:29 -04:00
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
2015-06-08 22:48:29 -04:00
return handler->OnPreKeyEvent(
_browserControl, browserWrapper, (KeyType)event.type, event.windows_key_code,
event.native_key_code, (CefEventFlags)event.modifiers, event.is_system_key == 1,
*is_keyboard_shortcut);
}
}
2015-06-08 22:48:29 -04:00
return false;
}
2014-03-09 13:49:35 +01:00
void ClientAdapter::OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
CefFrameWrapper frameWrapper(frame);
popupHandler->OnFrameLoadStart(_browserControl, gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper));
}
}
else
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
CefFrameWrapper frameWrapper(frame);
_browserControl->OnFrameLoadStart(gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper));
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
CefFrameWrapper frameWrapper(frame);
popupHandler->OnFrameLoadEnd(_browserControl, gcnew FrameLoadEndEventArgs(browserWrapper, %frameWrapper, httpStatusCode));
}
}
else
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
CefFrameWrapper frameWrapper(frame);
_browserControl->OnFrameLoadEnd(gcnew FrameLoadEndEventArgs(browserWrapper, %frameWrapper, httpStatusCode));
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
CefFrameWrapper frameWrapper(frame);
popupHandler->OnLoadError(_browserControl,
gcnew LoadErrorEventArgs(browserWrapper, %frameWrapper, (CefErrorCode)errorCode, StringUtils::ToClr(errorText), StringUtils::ToClr(failedUrl)));
}
}
else
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
CefFrameWrapper frameWrapper(frame);
_browserControl->OnLoadError(gcnew LoadErrorEventArgs(browserWrapper, %frameWrapper,
(CefErrorCode)errorCode, StringUtils::ToClr(errorText), StringUtils::ToClr(failedUrl)));
}
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool isRedirect)
2014-03-09 13:49:35 +01:00
{
if (browser->IsPopup())
2014-05-09 12:29:40 +10:00
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
CefFrameWrapper frameWrapper(frame);
CefRequestWrapper requestWrapper(request);
return popupHandler->OnBeforeBrowse(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, isRedirect);
}
2014-05-09 12:29:40 +10:00
}
else
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
CefFrameWrapper frameWrapper(frame);
CefRequestWrapper requestWrapper(request);
2014-03-09 13:49:35 +01:00
return handler->OnBeforeBrowse(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, isRedirect);
}
}
2015-06-08 22:48:29 -04:00
return false;
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnCertificateError(CefRefPtr<CefBrowser> browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr<CefSSLInfo> ssl_info, CefRefPtr<CefRequestCallback> callback)
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
// If callback is empty the error cannot be recovered from and the request will be canceled automatically.
// Still notify the user of the certificate error just don't provide a callback.
auto requestCallback = callback == NULL ? nullptr : gcnew CefRequestCallbackWrapper(callback);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnCertificateError(_browserControl, browserWrapper, (CefErrorCode)cert_error, StringUtils::ToClr(request_url), requestCallback);
}
bool ClientAdapter::OnQuotaRequest(CefRefPtr<CefBrowser> browser, const CefString& originUrl, int64 newSize, CefRefPtr<CefRequestCallback> callback)
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
auto requestCallback = gcnew CefRequestCallbackWrapper(callback);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnQuotaRequest(_browserControl, browserWrapper, StringUtils::ToClr(originUrl), newSize, requestCallback);
}
2014-04-14 16:28:44 +02:00
// CEF3 API: public virtual bool OnBeforePluginLoad( CefRefPtr< CefBrowser > browser, const CefString& url, const CefString& policy_url, CefRefPtr< CefWebPluginInfo > info );
// ---
// return value:
// false: Load Plugin (do not block it)
// true: Ignore Plugin (Block it)
bool ClientAdapter::OnBeforePluginLoad(CefRefPtr<CefBrowser> browser, const CefString& url, const CefString& policy_url, CefRefPtr<CefWebPluginInfo> info)
2014-04-14 16:28:44 +02:00
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
auto pluginInfo = TypeConversion::FromNative(info);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnBeforePluginLoad(_browserControl, browserWrapper, StringUtils::ToClr(url), StringUtils::ToClr(policy_url), pluginInfo);
2014-03-09 13:49:35 +01:00
}
2014-05-27 00:02:01 +10:00
void ClientAdapter::OnPluginCrashed(CefRefPtr<CefBrowser> browser, const CefString& plugin_path)
{
auto handler = _browserControl->RequestHandler;
2014-05-27 00:02:01 +10:00
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnPluginCrashed(_browserControl, browserWrapper, StringUtils::ToClr(plugin_path));
}
2014-05-27 00:02:01 +10:00
}
2014-05-25 13:36:34 +10:00
void ClientAdapter::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, TerminationStatus status)
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnRenderProcessTerminated(_browserControl, browserWrapper, (CefTerminationStatus)status);
}
}
void ClientAdapter::OnResourceRedirect(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefString& newUrl)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto managedNewUrl = StringUtils::ToClr(newUrl);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);;
CefFrameWrapper frameWrapper(frame);
CefRequestWrapper requestWrapper(request);
popupHandler->OnResourceRedirect(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, managedNewUrl);
newUrl = StringUtils::ToNative(managedNewUrl);
}
}
else
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto managedNewUrl = StringUtils::ToClr(newUrl);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);;
CefFrameWrapper frameWrapper(frame);
CefRequestWrapper requestWrapper(request);
handler->OnResourceRedirect(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, managedNewUrl);
newUrl = StringUtils::ToNative(managedNewUrl);
}
}
}
void ClientAdapter::OnProtocolExecution(CefRefPtr<CefBrowser> browser, const CefString& url, bool& allowOSExecution)
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
allowOSExecution = handler->OnProtocolExecution(_browserControl, browserWrapper, StringUtils::ToClr(url));
}
}
// Called on the IO thread before a resource is loaded. To allow the resource
// to load normally return NULL. To specify a handler for the resource return
// a CefResourceHandler object. The |request| object should not be modified in
// this callback.
CefRefPtr<CefResourceHandler> ClientAdapter::GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request)
2014-03-09 13:49:35 +01:00
{
auto factory = _browserControl->ResourceHandlerFactory;
2014-03-09 13:49:35 +01:00
if (factory == nullptr || !factory->HasHandlers)
2014-03-09 13:49:35 +01:00
{
return NULL;
2014-03-09 13:49:35 +01:00
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto frameWrapper = gcnew CefFrameWrapper(frame);
auto requestWrapper = gcnew CefRequestWrapper(request);
auto handler = factory->GetResourceHandler(_browserControl, browserWrapper, frameWrapper, requestWrapper);
2014-03-09 13:49:35 +01:00
if (handler == nullptr)
{
// Clean up our disposables if our factory doesn't want
// this request.
delete frameWrapper;
delete requestWrapper;
return NULL;
}
if (handler->GetType() == ResourceHandler::typeid)
{
auto resourceHandler = static_cast<ResourceHandler^>(handler);
if (resourceHandler->Type == ResourceHandlerType::File)
{
return new CefStreamResourceHandler(StringUtils::ToNative(resourceHandler->MimeType), CefStreamReader::CreateForFile(StringUtils::ToNative(resourceHandler->FilePath)));
}
}
// No need to pass browserWrapper for disposable lifetime management here
// because GetBrowserWrapper returned IBrowser^s are already properly
// managed.
return new ResourceHandlerWrapper(handler, nullptr, frameWrapper, requestWrapper);
}
cef_return_value_t ClientAdapter::OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefRequestCallback> callback)
{
if (browser->IsPopup())
{
auto popupHandler = _browserControl->PopupHandler;
if (popupHandler != nullptr)
{
auto frameWrapper = gcnew CefFrameWrapper(frame);
auto requestWrapper = gcnew CefRequestWrapper(request);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
auto requestCallback = gcnew CefRequestCallbackWrapper(callback, frameWrapper, requestWrapper);
return (cef_return_value_t)popupHandler->OnBeforeResourceLoad(_browserControl, browserWrapper, frameWrapper, requestWrapper, requestCallback);
}
}
else
{
auto handler = _browserControl->RequestHandler;
2014-03-09 13:49:35 +01:00
if (handler != nullptr)
{
auto frameWrapper = gcnew CefFrameWrapper(frame);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), false);
auto requestWrapper = gcnew CefRequestWrapper(request);
auto requestCallback = gcnew CefRequestCallbackWrapper(callback, frameWrapper, requestWrapper);
return (cef_return_value_t)handler->OnBeforeResourceLoad(_browserControl, browserWrapper, frameWrapper, requestWrapper, requestCallback);
}
}
2015-06-08 22:48:29 -04:00
return cef_return_value_t::RV_CONTINUE;
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::GetAuthCredentials(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, bool isProxy,
const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback)
{
auto handler = _browserControl->RequestHandler;
2014-03-09 13:49:35 +01:00
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto frameWrapper = gcnew CefFrameWrapper(frame);
auto callbackWrapper = gcnew CefAuthCallbackWrapper(callback, frameWrapper);
2014-03-09 13:49:35 +01:00
return handler->GetAuthCredentials(
_browserControl, browserWrapper, frameWrapper, isProxy,
2015-06-08 22:48:29 -04:00
StringUtils::ToClr(host), port, StringUtils::ToClr(realm),
StringUtils::ToClr(scheme), callbackWrapper);
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model)
{
auto handler = _browserControl->MenuHandler;
if (handler == nullptr)
{
return;
}
2014-03-09 13:49:35 +01:00
CefFrameWrapper frameWrapper(frame);
CefContextMenuParamsWrapper contextMenuParamsWrapper(params);
2015-06-11 12:28:20 +10:00
auto result = handler->OnBeforeContextMenu(_browserControl, %frameWrapper, %contextMenuParamsWrapper);
2014-11-05 12:10:04 +10:00
if (!result)
{
2014-11-05 00:26:58 +08:00
model->Clear();
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnGotFocus(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->FocusHandler;
if (handler == nullptr)
2014-11-25 22:33:12 +11:00
{
return;
}
2015-06-08 22:48:29 -04:00
// NOTE: a popup handler for OnGotFocus doesn't make sense yet because
// non-offscreen windows don't wrap popup browser's yet.
if (!browser->IsPopup())
{
handler->OnGotFocus();
}
}
bool ClientAdapter::OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source)
{
auto handler = _browserControl->FocusHandler;
if (handler == nullptr)
2014-11-25 22:33:12 +11:00
{
// Allow the focus to be set by default.
return false;
}
2015-06-08 22:48:29 -04:00
// NOTE: a popup handler for OnGotFocus doesn't make sense yet because
// non-offscreen windows don't wrap popup browser's yet.
if (!browser->IsPopup())
{
return handler->OnSetFocus((CefFocusSource)source);
}
// Allow the focus to be set by default.
return false;
}
2014-03-09 13:49:35 +01:00
void ClientAdapter::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next)
{
auto handler = _browserControl->FocusHandler;
if (handler == nullptr)
2014-11-25 22:33:12 +11:00
{
return;
}
2015-06-08 22:48:29 -04:00
// NOTE: a popup handler for OnGotFocus doesn't make sense yet because
// non-offscreen windows don't wrap popup browser's yet.
if (!browser->IsPopup())
{
handler->OnTakeFocus(next);
}
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnJSDialog(CefRefPtr<CefBrowser> browser, const CefString& origin_url, const CefString& accept_lang,
JSDialogType dialog_type, const CefString& message_text, const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> callback, bool& suppress_message)
{
auto handler = _browserControl->JsDialogHandler;
2014-03-09 13:49:35 +01:00
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto callbackWrapper = gcnew CefJSDialogCallbackWrapper(callback);
return handler->OnJSDialog(_browserControl, browserWrapper,
2015-06-08 22:48:29 -04:00
StringUtils::ToClr(origin_url), StringUtils::ToClr(accept_lang), (CefJsDialogType)dialog_type,
StringUtils::ToClr(message_text), StringUtils::ToClr(default_prompt_text), callbackWrapper, suppress_message);
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser, const CefString& message_text, bool is_reload, CefRefPtr<CefJSDialogCallback> callback)
{
auto handler = _browserControl->JsDialogHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto callbackWrapper = gcnew CefJSDialogCallbackWrapper(callback);
return handler->OnJSBeforeUnload(_browserControl, browserWrapper, StringUtils::ToClr(message_text), is_reload, callbackWrapper);
}
bool ClientAdapter::OnFileDialog(CefRefPtr<CefBrowser> browser, FileDialogMode mode, const CefString& title,
const CefString& default_file_path, const std::vector<CefString>& accept_filters, int selected_accept_filter,
CefRefPtr<CefFileDialogCallback> callback)
{
auto handler = _browserControl->DialogHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
2015-06-01 16:27:42 +10:00
auto callbackWrapper = gcnew CefFileDialogCallbackWrapper(callback);
return handler->OnFileDialog(_browserControl, browserWrapper, (CefFileDialogMode)mode, StringUtils::ToClr(title), StringUtils::ToClr(default_file_path), StringUtils::ToClr(accept_filters), selected_accept_filter, callbackWrapper);
}
bool ClientAdapter::OnDragEnter(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDragData> dragData, DragOperationsMask mask)
{
auto handler = _browserControl->DragHandler;
if (handler == nullptr)
{
return false;
}
2015-06-11 12:25:38 +10:00
CefDragDataWrapper dragDataWrapper(dragData);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnDragEnter(_browserControl, browserWrapper, %dragDataWrapper, (CefSharp::DragOperationsMask)mask);
}
bool ClientAdapter::OnRequestGeolocationPermission(CefRefPtr<CefBrowser> browser, const CefString& requesting_url, int request_id, CefRefPtr<CefGeolocationCallback> callback)
{
auto handler = _browserControl->GeolocationHandler;
if (handler == nullptr)
{
// Default deny, as CEF does.
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
2015-06-01 11:56:50 +10:00
auto callbackWrapper = gcnew CefGeolocationCallbackWrapper(callback);
return handler->OnRequestGeolocationPermission(_browserControl, browserWrapper, StringUtils::ToClr(requesting_url), request_id, callbackWrapper);
}
void ClientAdapter::OnCancelGeolocationPermission(CefRefPtr<CefBrowser> browser, const CefString& requesting_url, int request_id)
{
auto handler = _browserControl->GeolocationHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnCancelGeolocationPermission(_browserControl, browserWrapper, StringUtils::ToClr(requesting_url), request_id);
}
}
void ClientAdapter::OnBeforeDownload(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback)
{
auto handler = _browserControl->DownloadHandler;
if(handler != nullptr)
{
auto downloadItem = TypeConversion::FromNative(download_item);
downloadItem->SuggestedFileName = StringUtils::ToClr(suggested_name);
2015-06-01 11:48:12 +10:00
auto callbackWrapper = gcnew CefBeforeDownloadCallbackWrapper(callback);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
2015-06-01 11:48:12 +10:00
handler->OnBeforeDownload(browserWrapper, downloadItem, callbackWrapper);
}
};
void ClientAdapter::OnDownloadUpdated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item,
CefRefPtr<CefDownloadItemCallback> callback)
{
auto handler = _browserControl->DownloadHandler;
if(handler != nullptr)
{
auto callbackWrapper = gcnew CefDownloadItemCallbackWrapper(callback);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnDownloadUpdated(browserWrapper, TypeConversion::FromNative(download_item), callbackWrapper);
}
}
bool ClientAdapter::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
{
auto handled = false;
auto name = message->GetName();
2015-07-14 10:59:10 +02:00
auto argList = message->GetArgumentList();
IJavascriptCallbackFactory^ callbackFactory;
_javascriptCallbackFactories->TryGetValue(browser->GetIdentifier(), callbackFactory);
if (name == kEvaluateJavascriptResponse || name == kJavascriptCallbackResponse)
{
auto success = argList->GetBool(0);
auto callbackId = GetInt64(argList, 1);
auto pendingTask = _pendingTaskRepository->RemovePendingTask(callbackId);
if (pendingTask != nullptr)
{
auto response = gcnew JavascriptResponse();
response->Success = success;
if (success)
{
response->Result = DeserializeObject(argList, 2, callbackFactory);
}
else
{
response->Message = StringUtils::ToClr(argList->GetString(2));
}
pendingTask->SetResult(response);
}
2015-07-14 10:59:10 +02:00
handled = true;
}
else if (name == kJavascriptAsyncMethodCallRequest)
2015-07-14 10:59:10 +02:00
{
if (!browser->IsPopup())
{
auto objectId = GetInt64(argList, 0);
auto callbackId = GetInt64(argList, 1);
auto methodName = StringUtils::ToClr(argList->GetString(2));
auto arguments = argList->GetList(3);
auto methodInvocation = gcnew MethodInvocation(objectId, methodName, (callbackId > 0 ? Nullable<int64>(callbackId) : Nullable<int64>()));
2015-07-14 10:59:10 +02:00
for (auto i = 0; i < arguments->GetSize(); i++)
{
methodInvocation->Parameters->Add(DeserializeObject(arguments, i, callbackFactory));
2015-07-14 10:59:10 +02:00
}
_browserAdapter->MethodRunnerQueue->Enqueue(methodInvocation);
2015-07-14 10:59:10 +02:00
}
handled = true;
}
return handled;
}
Task<JavascriptResponse^>^ ClientAdapter::EvaluateScriptAsync(int browserId, bool isBrowserPopup, int64 frameId, String^ script, Nullable<TimeSpan> timeout)
{
//create a new taskcompletionsource
auto idAndComplectionSource = _pendingTaskRepository->CreatePendingTask(timeout);
auto message = CefProcessMessage::Create(kEvaluateJavascriptRequest);
auto argList = message->GetArgumentList();
SetInt64(frameId, argList, 0);
SetInt64(idAndComplectionSource.Key, argList, 1);
argList->SetString(2, StringUtils::ToNative(script));
auto browserWrapper = static_cast<CefSharpBrowserWrapper^>(GetBrowserWrapper(browserId, isBrowserPopup));
browserWrapper->SendProcessMessage(CefProcessId::PID_RENDERER, message);
return idAndComplectionSource.Value->Task;
}
PendingTaskRepository<JavascriptResponse^>^ ClientAdapter::GetPendingTaskRepository()
{
return _pendingTaskRepository;
}
void ClientAdapter::MethodInvocationComplete(MethodInvocationResult^ result)
{
if (result->CallbackId.HasValue)
{
auto message = CefProcessMessage::Create(kJavascriptAsyncMethodCallResponse);
auto argList = message->GetArgumentList();
SetInt64(result->CallbackId.Value, argList, 0);
argList->SetBool(1, result->Success);
if (result->Success)
{
SerializeV8Object(result->Result, argList, 2);
}
else
{
argList->SetString(2, StringUtils::ToNative(result->Message));
}
_cefBrowser->SendProcessMessage(CefProcessId::PID_RENDERER, message);
}
}
2014-03-09 13:49:35 +01:00
}
}