SIGN IN SIGN UP
cefsharp / CefSharp UNCLAIMED

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

0 0 0 C#
// Copyright © 2010 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 "ClientAdapter.h"
#include "include\cef_client.h"
#include "include\wrapper\cef_stream_resource_handler.h"
#include "CefAuthCallbackWrapper.h"
#include "CefBeforeDownloadCallbackWrapper.h"
#include "CefCertificateCallbackWrapper.h"
#include "CefContextMenuParamsWrapper.h"
#include "CefDownloadItemCallbackWrapper.h"
Refactor CefSharp.Core into CefSharp.Core.Runtime (#3311) * Net Core - Rename CefSharp.Core.dll to CefSharp.Core.Runtime.dll Partial rename, only Net Core, folder not renamed * Net Core - Rename CefSharp.Core.RefAssembly to CefSharp.Core.netcore Remove GenApi * Core - Rename CefDragDataWrapper to DragData Move into CefSharp.Core namespace * WinForms/WPF/OffScreen - Migrate from GitLink command line to Nuget package * Net Core - Refactor to have CefSharp.Core.dll contain only public Api * Net Core - Remove CefSharp.Core.RefAssembly * Net Core - Change CefSharp.Core.netcore output folder * Net Core - Restructure nuget packages * Net Core - Add Cefsharp.Core.Runtime.RefAssembly * Net Core - Hide CLI/C++ classes from intellisense Make sure users don't attempt to load them directly * Rename CefSharp.Core to CefSharp.Core.Runtime * Core - Restructure Net 4.5.2 packages to use CefSharp.Core.dll anycpu variant Attempt to load CefSharp.Core.Runtime at runtime rather than having to use msbuild to copy the correct version * Rename CefSharp.Core.netcore to CefSharp.Core * WPF/WinForms/OffScreen - Change from x86/64 to AnyCPU As they are all managed assemblies they can target AnyCPU. Includes CefSharp.dll * Convert RequestContextBuilder from C++ to C# Now part of the CefSharp.Core PublicApi * Update version number to 87.1.11 * Migrate more of the public Api to C# * Net Core - Basic restructure complete * Net Core - ModuleInitializer (Doesn't work yet) * Remove direct references to BrowserSettings * Net Core - ModuleInitializer load CefShar.Core.Runtime.dl * Net Core - Load libcef.dll via CLR Module initializer If no RID is specified then we can load libcef.dll using the module initializer * Add version to CefSharp.Core * Remove dependency on CefSharp.Core.Runtime Rewrite common targets * AnyCPU app.config transform Improve AnyCPU support * Improve Net Core 3 support Only delete CefSharp.Core.Runtime.dll when AnyCPU * Nuget - Add CefSharp.Core.Runtime reference when TargetFramework = NetCore * Fix Typos Based on #3306 * Net Core - Rename CefSharp.Core.Runtime RefAssembly source file * Net Full - Generate CefSharp.Core.Runtime Ref Assembly For now the powershell build script generates the .cs file based on a x86 release build.ps1 It's not possible to directly install GenApi as it requires a Sdk style project * Net Core - Old packages copy files to required folders * Test - Install newer .Net Compiler and set Lang Version to 7.3 * Net Core - Exclude Net 452 Runtime generated reference source * Core - Add Refactoring TODO * Ref Assembly - Generate source as part of build - Move ref assembly source generate into GenerateRefAssemblySource.ps1 - Call before project build Runs locally, see if Appveyor has a problem with the powershell script execution * Core - Add more factory methods to create instances of managed wrappers * Net Core - Make Initialzier properties internal Not quite sure what the public API should look like as yet, so making internal for now.
2020-12-16 10:47:34 +10:00
#include "DragData.h"
#include "CefFileDialogCallbackWrapper.h"
#include "CefFrameWrapper.h"
#include "CefJSDialogCallbackWrapper.h"
#include "CefMenuModelWrapper.h"
#include "Request.h"
#include "CefResourceRequestHandlerAdapter.h"
#include "CefRequestCallbackWrapper.h"
2015-10-12 08:03:50 +10:00
#include "CefRunContextMenuCallbackWrapper.h"
#include "CefPermissionPromptCallbackWrapper.h"
#include "CefSslInfoWrapper.h"
#include "CefBrowserWrapper.h"
#include "CefMediaAccessCallbackWrapper.h"
#include "ManagedCefBrowserAdapter.h"
#include "Messaging\Messages.h"
#include "PopupFeatures.h"
#include "Serialization\Primitives.h"
#include "Serialization\V8Serialization.h"
#include "Serialization\JsObjectsSerialization.h"
#include "Serialization\ObjectsSerialization.h"
#include "TypeConversion.h"
#include "WindowInfo.h"
using namespace CefSharp::Internals::Messaging;
using namespace CefSharp::Internals::Serialization;
using namespace System::Security::Cryptography::X509Certificates;
2014-03-09 13:49:35 +01:00
namespace CefSharp
{
namespace Internals
{
IBrowser^ ClientAdapter::GetBrowserWrapper(int browserId)
{
if (_cefBrowser.get())
{
if (_cefBrowser->GetIdentifier() == browserId)
{
return _browser;
}
//IJavascriptCallbacks that are finalized after the browser has been Disposed
//but before the IBrowserAdapter.IsDisposed is set might end up here
//attempting to access _popupBrowsers which has been set to null already.
auto popupBrowsers = _popupBrowsers;
if (Object::ReferenceEquals(popupBrowsers, nullptr))
{
return nullptr;
}
IBrowser^ popupBrowser;
if (popupBrowsers->TryGetValue(browserId, popupBrowser))
{
return popupBrowser;
}
}
return nullptr;
}
IBrowser^ ClientAdapter::GetBrowserWrapper(int browserId, bool isPopup)
{
if (!isPopup)
{
return _browser;
}
IBrowser^ popupBrowser;
if (_popupBrowsers->TryGetValue(browserId, popupBrowser))
{
return popupBrowser;
}
// For popups that were hosted using a ChromiumWebBrowser instance
if (_browserControl->HasParent)
{
return _browser;
}
return nullptr;
}
// Is a main browser if isPopuo == false or the IBrowser instance is directly associated
// with the ChromiumWebBrowser instance. Should be true in cases
// where ChromiumWebBrowser is instanciated directly or
// when a popup is hosted in a ChromiumWebBrowser instance
// For popups hosted in ChromiumWebBrowser instances it's important
// that DevTools popups return false;
bool ClientAdapter::IsMainBrowser(bool isPopup, int browserId)
{
// Main browser is always true
if (!isPopup)
{
return true;
}
// If popup and HasParent == false then always false
if (!_browserControl->HasParent)
{
return false;
}
// This method is called from OnAfterCreated before _cefBrowser is set
// If the _cefBrowser reference is null then this should be a ChromiumWebBrowser
// hosted as a popup
if (!_cefBrowser.get())
{
return true;
}
// For popups hosted in ChromiumWebBrowser instance directly (non DevTools popup)
// then return true;
if (_cefBrowser->GetIdentifier() == browserId)
{
return true;
}
return false;
}
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,
CefRefPtr<CefClient>& client, CefBrowserSettings& settings, CefRefPtr<CefDictionaryValue>& extraInfo, bool* no_javascript_access)
2014-03-09 13:49:35 +01:00
{
auto handler = _browserControl->LifeSpanHandler;
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);
PopupFeatures popupFeaturesWrapper(&popupFeatures);
BrowserSettings browserSettingsWrapper(&settings);
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, %popupFeaturesWrapper,
%windowInfoWrapper, %browserSettingsWrapper, *no_javascript_access, newBrowser);
2015-05-05 17:31:46 +01:00
if (newBrowser != nullptr)
2015-05-07 23:40:56 +01:00
{
//newBrowser should never be set to _browserControl (I've seen user code where someone attepted to do this).
//So throw exception to make that perfectly clear.
if (Object::ReferenceEquals(_browserControl, newBrowser))
{
throw gcnew Exception("newBrowser should be a new instance of ChromiumWebBrowser or null.");
}
//newBrowser is not null and result is true, whilst the documentation clearly states returning true will
//cancel popup creation people keep expecting that newBrowser will do something which it won't
if (result == true)
{
throw gcnew Exception("returning true cancels popup creation, if you return true newBrowser should be set to null."
+ "Previously no exception was thrown in this instance, this exception has been added to reduce the number of"
+ " support requests from people returning true and setting newBrowser and expecting popups to work.");
}
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
{
//This should already be set using the SetAsPopup extension, just making doubly sure
newBrowserInternal->HasParent = true;
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)
{
BrowserRefCounter::Instance->Increment(_browserControl->GetType());
auto browserWrapper = gcnew CefBrowserWrapper(browser);
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
2014-03-09 13:49:35 +01:00
{
_browserHwnd = browser->GetHost()->GetWindowHandle();
_cefBrowser = browser;
_browser = browserWrapper;
if (!Object::ReferenceEquals(_browserAdapter, nullptr))
{
_browserAdapter->OnAfterBrowserCreated(browserWrapper);
}
}
else
{
// Add to the list of popup browsers.
_popupBrowsers->Add(browser->GetIdentifier(), browserWrapper);
}
2015-05-07 18:32:14 +01:00
auto handler = _browserControl->LifeSpanHandler;
2015-05-07 18:32:14 +01:00
if (handler != nullptr)
{
handler->OnAfterCreated(_browserControl, browserWrapper);
}
2014-03-09 13:49:35 +01:00
}
2015-08-17 13:46:28 +10:00
bool ClientAdapter::DoClose(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->LifeSpanHandler;
if (handler != nullptr)
{
//By this point it's possible IBrowser references have been disposed
//Rather than attempting to rework the rather complex closing logic
//It's easier to pass in a new wrapper and dispose it straight away
CefBrowserWrapper browserWrapper(browser);
return handler->DoClose(_browserControl, %browserWrapper);
2015-08-17 13:46:28 +10:00
}
return false;
}
2014-03-09 13:49:35 +01:00
void ClientAdapter::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->LifeSpanHandler;
if (handler != nullptr)
{
//By this point it's possible IBrowser references have been disposed
//Rather than attempting to rework the rather complex closing logic
//It's easier to pass in a new wrapper and dispose it straight away
CefBrowserWrapper browserWrapper(browser);
handler->OnBeforeClose(_browserControl, %browserWrapper);
}
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_cefBrowser = nullptr;
}
else
{
// Remove from the browser popup list.
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true);
_popupBrowsers->Remove(browser->GetIdentifier());
// Dispose the CefBrowserWrapper
delete browserWrapper;
}
BrowserRefCounter::Instance->Decrement(_browserControl->GetType());
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 (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->SetLoadingStateChange(args);
}
auto handler = _browserControl->LoadHandler;
if (handler != nullptr)
{
handler->OnLoadingStateChange(_browserControl, 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(browserWrapper, StringUtils::ToClr(address));
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
2014-03-09 13:49:35 +01:00
{
_browserControl->SetAddress(args);
}
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
handler->OnAddressChanged(_browserControl, args);
2014-03-09 13:49:35 +01:00
}
}
bool ClientAdapter::OnAutoResize(CefRefPtr<CefBrowser> browser, const CefSize& new_size)
{
auto handler = _browserControl->DisplayHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnAutoResize(_browserControl, browserWrapper, CefSharp::Structs::Size(new_size.width, new_size.height));
}
bool ClientAdapter::OnCursorChange(CefRefPtr<CefBrowser> browser, CefCursorHandle cursor, cef_cursor_type_t type, const CefCursorInfo& custom_cursor_info)
{
auto handler = _browserControl->DisplayHandler;
if (handler == nullptr)
{
InternalCursorChange(browser, cursor, type, custom_cursor_info);
return false;
}
CursorInfo customCursorInfo;
//TODO: this is duplicated in RenderClientAdapter::InternalCursorChange
//Only create the struct when we actually have a custom cursor
if (type == cef_cursor_type_t::CT_CUSTOM)
{
Point hotspot = Point(custom_cursor_info.hotspot.x, custom_cursor_info.hotspot.y);
Size size = Size(custom_cursor_info.size.width, custom_cursor_info.size.height);
customCursorInfo = CursorInfo(IntPtr((void*)custom_cursor_info.buffer), hotspot, custom_cursor_info.image_scale_factor, size);
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto handled = handler->OnCursorChange(_browserControl, browserWrapper, (IntPtr)cursor, (CefSharp::Enums::CursorType)type, customCursorInfo);
if (handled)
{
return true;
}
InternalCursorChange(browser, cursor, type, custom_cursor_info);
return false;
};
void ClientAdapter::InternalCursorChange(CefRefPtr<CefBrowser> browser, CefCursorHandle cursor, cef_cursor_type_t type, const CefCursorInfo& custom_cursor_info)
{
}
2014-03-09 13:49:35 +01:00
void ClientAdapter::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto args = gcnew TitleChangedEventArgs(browserWrapper, StringUtils::ToClr(title));
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->SetTitle(args);
}
else
{
// Set the popup window title
auto hwnd = browser->GetHost()->GetWindowHandle();
SetWindowText(hwnd, std::wstring(title).c_str());
}
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
handler->OnTitleChanged(_browserControl, args);
}
2014-03-09 13:49:35 +01:00
}
void ClientAdapter::OnFaviconURLChange(CefRefPtr<CefBrowser> browser, const std::vector<CefString>& iconUrls)
{
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnFaviconUrlChange(_browserControl, browserWrapper, StringUtils::ToClr(iconUrls));
}
}
void ClientAdapter::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen)
{
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnFullscreenModeChange(_browserControl, browserWrapper, fullscreen);
}
}
void ClientAdapter::OnLoadingProgressChange(CefRefPtr<CefBrowser> browser, double progress)
{
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnLoadingProgressChange(_browserControl, browserWrapper, progress);
}
}
2014-03-09 13:49:35 +01:00
bool ClientAdapter::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text)
{
auto tooltip = StringUtils::ToClr(text);
bool hasChanged = tooltip != _tooltip;
bool returnFlag = true;
2014-03-09 13:49:35 +01:00
//NOTE: Only called if tooltip changed otherwise called many times
// also only called when using OSR, https://github.com/chromiumembedded/cef/issues/783
if (hasChanged)
2014-03-09 13:49:35 +01:00
{
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
returnFlag = handler->OnTooltipChanged(_browserControl, tooltip);
}
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_tooltip = tooltip;
_browserControl->SetTooltipText(_tooltip);
}
2014-03-09 13:49:35 +01:00
}
return returnFlag;
2014-03-09 13:49:35 +01:00
}
2018-02-05 17:30:44 +10:00
bool ClientAdapter::OnConsoleMessage(CefRefPtr<CefBrowser> browser, cef_log_severity_t level, const CefString& message, const CefString& source, int line)
2014-03-09 13:49:35 +01:00
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto args = gcnew ConsoleMessageEventArgs(browserWrapper, (LogSeverity)level, StringUtils::ToClr(message), StringUtils::ToClr(source), line);
2014-03-09 13:49:35 +01:00
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->OnConsoleMessage(args);
}
auto handler = _browserControl->DisplayHandler;
if (handler == nullptr)
{
return false;
}
return handler->OnConsoleMessage(_browserControl, args);
2014-03-09 13:49:35 +01:00
}
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 (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->OnStatusMessage(args);
}
auto handler = _browserControl->DisplayHandler;
if (handler != nullptr)
{
handler->OnStatusMessage(_browserControl, args);
}
}
2014-03-09 13:49:35 +01:00
bool ClientAdapter::OnKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent& event, CefEventHandle os_event)
{
auto handler = _browserControl->KeyboardHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->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
}
bool ClientAdapter::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent& event, CefEventHandle os_event, bool* is_keyboard_shortcut)
{
auto handler = _browserControl->KeyboardHandler;
if (handler == nullptr)
{
return false;
}
2015-06-08 22:48:29 -04:00
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
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);
}
void ClientAdapter::OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, TransitionType transitionType)
2014-03-09 13:49:35 +01:00
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
2014-03-09 13:49:35 +01:00
{
_browserControl->OnFrameLoadStart(gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper, (CefSharp::TransitionType)transitionType));
}
auto handler = _browserControl->LoadHandler;
if (handler != nullptr)
{
handler->OnFrameLoadStart(_browserControl, gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper, (CefSharp::TransitionType)transitionType));
2014-03-09 13:49:35 +01:00
}
}
void ClientAdapter::OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->OnFrameLoadEnd(gcnew FrameLoadEndEventArgs(browserWrapper, %frameWrapper, httpStatusCode));
2014-03-09 13:49:35 +01:00
}
auto handler = _browserControl->LoadHandler;
if (handler != nullptr)
{
handler->OnFrameLoadEnd(_browserControl, 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)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
if (IsMainBrowser(browser->IsPopup(), browser->GetIdentifier()))
{
_browserControl->OnLoadError(gcnew LoadErrorEventArgs(browserWrapper, %frameWrapper,
(CefErrorCode)errorCode, StringUtils::ToClr(errorText), StringUtils::ToClr(failedUrl)));
}
auto handler = _browserControl->LoadHandler;
if (handler != nullptr)
{
handler->OnLoadError(_browserControl,
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 userGesture, bool isRedirect)
2014-03-09 13:49:35 +01:00
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
2014-03-09 13:49:35 +01:00
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
Request requestWrapper(request);
return handler->OnBeforeBrowse(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, userGesture, isRedirect);
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& targetUrl,
CefRequestHandler::WindowOpenDisposition targetDisposition, bool userGesture)
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
return handler->OnOpenUrlFromTab(_browserControl, browserWrapper, %frameWrapper, StringUtils::ToClr(targetUrl), (CefSharp::WindowOpenDisposition)targetDisposition, userGesture);
}
CefRefPtr<CefResourceRequestHandler> ClientAdapter::GetResourceRequestHandler(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool isNavigation, bool isDownload, const CefString& requestInitiator, bool& disableDefaultHandling)
{
auto handler = _browserControl->RequestHandler;
auto resourceRequestHandlerFactory = _browserControl->ResourceRequestHandlerFactory;
//No handler and no factory, we'll just return null
if (handler == nullptr && resourceRequestHandlerFactory == nullptr)
{
return nullptr;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
Request requestWrapper(request);
if (handler != nullptr)
{
auto resourceRequestHandler = handler->GetResourceRequestHandler(_browserControl, browserWrapper, %frameWrapper,
%requestWrapper, isNavigation, isDownload, StringUtils::ToClr(requestInitiator), disableDefaultHandling);
if (resourceRequestHandler != nullptr)
{
return new CefResourceRequestHandlerAdapter(_browserControl, resourceRequestHandler);
}
}
if (resourceRequestHandlerFactory != nullptr && resourceRequestHandlerFactory->HasHandlers)
{
auto factoryHandler = resourceRequestHandlerFactory->GetResourceRequestHandler(_browserControl, browserWrapper, %frameWrapper,
%requestWrapper, isNavigation, isDownload, StringUtils::ToClr(requestInitiator), disableDefaultHandling);
if (factoryHandler != nullptr)
{
return new CefResourceRequestHandlerAdapter(_browserControl, factoryHandler);
}
}
return nullptr;
}
bool ClientAdapter::OnCertificateError(CefRefPtr<CefBrowser> browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr<CefSSLInfo> ssl_info, CefRefPtr<CefCallback> 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 == nullptr ? nullptr : gcnew CefRequestCallbackWrapper(callback);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto sslInfoWrapper = gcnew CefSslInfoWrapper(ssl_info);
return handler->OnCertificateError(_browserControl, browserWrapper, (CefErrorCode)cert_error, StringUtils::ToClr(request_url), sslInfoWrapper, requestCallback);
}
void ClientAdapter::OnRenderViewReady(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnRenderViewReady(_browserControl, browserWrapper);
}
}
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::OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->RequestHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnDocumentAvailableInMainFrame(_browserControl, browserWrapper);
}
}
bool ClientAdapter::GetAuthCredentials(CefRefPtr<CefBrowser> browser, const CefString& originUrl, bool isProxy,
2014-03-09 13:49:35 +01:00
const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback)
{
if (isProxy && CefSharpSettings::Proxy != nullptr && CefSharpSettings::Proxy->IP == StringUtils::ToClr(host) && CefSharpSettings::Proxy->HasUsernameAndPassword())
{
callback->Continue(StringUtils::ToNative(CefSharpSettings::Proxy->Username), StringUtils::ToNative(CefSharpSettings::Proxy->Password));
return true;
}
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 callbackWrapper = gcnew CefAuthCallbackWrapper(callback);
2014-03-09 13:49:35 +01:00
return handler->GetAuthCredentials(
_browserControl, browserWrapper, StringUtils::ToClr(originUrl), isProxy,
StringUtils::ToClr(host), port, StringUtils::ToClr(realm),
StringUtils::ToClr(scheme), callbackWrapper);
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnSelectClientCertificate(CefRefPtr<CefBrowser> browser, bool isProxy, const CefString& host,
int port, const CefRequestHandler::X509CertificateList& certificates, CefRefPtr<CefSelectClientCertificateCallback> callback)
{
auto handler = _browserControl->RequestHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto list = gcnew X509Certificate2Collection();
// Create a copy of the vector in an attempt to fix #2948
CefRequestHandler::X509CertificateList certs;
std::vector<CefRefPtr<CefX509Certificate> >::const_iterator it =
certificates.begin();
for (; it != certificates.end(); ++it)
{
auto bytes((*it)->GetDEREncoded());
auto byteSize = bytes->GetSize();
auto bufferByte = gcnew cli::array<Byte>(byteSize);
pin_ptr<Byte> src = &bufferByte[0]; // pin pointer to first element in arr
bytes->GetData(static_cast<void*>(src), byteSize, 0);
auto cert = gcnew X509Certificate2(bufferByte);
list->Add(cert);
certs.push_back(*it);
}
auto callbackWrapper = gcnew CefCertificateCallbackWrapper(callback, certs);
return handler->OnSelectClientCertificate(
_browserControl, browserWrapper, isProxy,
StringUtils::ToClr(host), port, list, 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)
2014-11-05 12:10:04 +10:00
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
CefContextMenuParamsWrapper contextMenuParamsWrapper(params);
CefMenuModelWrapper menuModelWrapper(model);
handler->OnBeforeContextMenu(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper, %menuModelWrapper);
}
}
bool ClientAdapter::OnContextMenuCommand(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params, int commandId, EventFlags eventFlags)
{
auto handler = _browserControl->MenuHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
CefContextMenuParamsWrapper contextMenuParamsWrapper(params);
return handler->OnContextMenuCommand(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper,
(CefMenuCommand)commandId, (CefEventFlags)eventFlags);
}
2015-09-01 21:56:17 +10:00
return false;
}
void ClientAdapter::OnContextMenuDismissed(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame)
{
auto handler = _browserControl->MenuHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
handler->OnContextMenuDismissed(_browserControl, browserWrapper, %frameWrapper);
}
2014-03-09 13:49:35 +01:00
}
2015-10-12 08:03:50 +10:00
bool ClientAdapter::RunContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model, CefRefPtr<CefRunContextMenuCallback> callback)
{
auto handler = _browserControl->MenuHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
2015-10-12 08:03:50 +10:00
CefFrameWrapper frameWrapper(frame);
CefContextMenuParamsWrapper contextMenuParamsWrapper(params);
CefMenuModelWrapper menuModelWrapper(model);
auto callbackWrapper = gcnew CefRunContextMenuCallbackWrapper(callback);
return handler->RunContextMenu(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper, %menuModelWrapper, callbackWrapper);
}
void ClientAdapter::OnGotFocus(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->FocusHandler;
if (handler == nullptr)
2014-11-25 22:33:12 +11:00
{
return;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnGotFocus(_browserControl, browserWrapper);
}
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;
}
2018-08-07 20:30:03 +10:00
//For DevTools (which is hosted as a popup) OnSetFocus is called before OnAfterCreated so we don't
// have a reference to the standard popup IBrowser wrapper, so we just pass a
// short term reference.
CefBrowserWrapper browserWrapper(browser);
return handler->OnSetFocus(_browserControl, %browserWrapper, (CefFocusSource)source);
}
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;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnTakeFocus(_browserControl, browserWrapper, next);
2014-03-09 13:49:35 +01:00
}
bool ClientAdapter::OnJSDialog(CefRefPtr<CefBrowser> browser, const CefString& origin_url,
2014-03-09 13:49:35 +01:00
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,
StringUtils::ToClr(origin_url), (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->OnBeforeUnloadDialog(_browserControl, browserWrapper, StringUtils::ToClr(message_text), is_reload, callbackWrapper);
}
void ClientAdapter::OnResetDialogState(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->JsDialogHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnResetDialogState(_browserControl, browserWrapper);
}
}
void ClientAdapter::OnDialogClosed(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->JsDialogHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnDialogClosed(_browserControl, browserWrapper);
}
}
bool ClientAdapter::OnFileDialog(CefRefPtr<CefBrowser> browser, FileDialogMode mode, const CefString& title,
const CefString& default_file_path, const std::vector<CefString>& accept_filters,
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),
callbackWrapper);
}
bool ClientAdapter::OnDragEnter(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDragData> dragData, DragOperationsMask mask)
{
auto handler = _browserControl->DragHandler;
if (handler == nullptr)
{
return false;
}
Refactor CefSharp.Core into CefSharp.Core.Runtime (#3311) * Net Core - Rename CefSharp.Core.dll to CefSharp.Core.Runtime.dll Partial rename, only Net Core, folder not renamed * Net Core - Rename CefSharp.Core.RefAssembly to CefSharp.Core.netcore Remove GenApi * Core - Rename CefDragDataWrapper to DragData Move into CefSharp.Core namespace * WinForms/WPF/OffScreen - Migrate from GitLink command line to Nuget package * Net Core - Refactor to have CefSharp.Core.dll contain only public Api * Net Core - Remove CefSharp.Core.RefAssembly * Net Core - Change CefSharp.Core.netcore output folder * Net Core - Restructure nuget packages * Net Core - Add Cefsharp.Core.Runtime.RefAssembly * Net Core - Hide CLI/C++ classes from intellisense Make sure users don't attempt to load them directly * Rename CefSharp.Core to CefSharp.Core.Runtime * Core - Restructure Net 4.5.2 packages to use CefSharp.Core.dll anycpu variant Attempt to load CefSharp.Core.Runtime at runtime rather than having to use msbuild to copy the correct version * Rename CefSharp.Core.netcore to CefSharp.Core * WPF/WinForms/OffScreen - Change from x86/64 to AnyCPU As they are all managed assemblies they can target AnyCPU. Includes CefSharp.dll * Convert RequestContextBuilder from C++ to C# Now part of the CefSharp.Core PublicApi * Update version number to 87.1.11 * Migrate more of the public Api to C# * Net Core - Basic restructure complete * Net Core - ModuleInitializer (Doesn't work yet) * Remove direct references to BrowserSettings * Net Core - ModuleInitializer load CefShar.Core.Runtime.dl * Net Core - Load libcef.dll via CLR Module initializer If no RID is specified then we can load libcef.dll using the module initializer * Add version to CefSharp.Core * Remove dependency on CefSharp.Core.Runtime Rewrite common targets * AnyCPU app.config transform Improve AnyCPU support * Improve Net Core 3 support Only delete CefSharp.Core.Runtime.dll when AnyCPU * Nuget - Add CefSharp.Core.Runtime reference when TargetFramework = NetCore * Fix Typos Based on #3306 * Net Core - Rename CefSharp.Core.Runtime RefAssembly source file * Net Full - Generate CefSharp.Core.Runtime Ref Assembly For now the powershell build script generates the .cs file based on a x86 release build.ps1 It's not possible to directly install GenApi as it requires a Sdk style project * Net Core - Old packages copy files to required folders * Test - Install newer .Net Compiler and set Lang Version to 7.3 * Net Core - Exclude Net 452 Runtime generated reference source * Core - Add Refactoring TODO * Ref Assembly - Generate source as part of build - Move ref assembly source generate into GenerateRefAssemblySource.ps1 - Call before project build Runs locally, see if Appveyor has a problem with the powershell script execution * Core - Add more factory methods to create instances of managed wrappers * Net Core - Make Initialzier properties internal Not quite sure what the public API should look like as yet, so making internal for now.
2020-12-16 10:47:34 +10:00
DragData dragDataWrapper(dragData);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->OnDragEnter(_browserControl, browserWrapper, %dragDataWrapper, (CefSharp::Enums::DragOperationsMask)mask);
}
void ClientAdapter::OnDraggableRegionsChanged(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const std::vector<CefDraggableRegion>& regions)
{
auto handler = _browserControl->DragHandler;
if (handler != nullptr)
{
auto regionsList = TypeConversion::FromNative(regions);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
return handler->OnDraggableRegionsChanged(_browserControl, browserWrapper, %frameWrapper, regionsList);
}
}
bool ClientAdapter::CanDownload(CefRefPtr<CefBrowser> browser, const CefString& url, const CefString& request_method)
{
auto handler = _browserControl->DownloadHandler;
if (handler == nullptr)
{
return true;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
return handler->CanDownload(_browserControl, browserWrapper, StringUtils::ToClr(url), StringUtils::ToClr(request_method));
}
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(_browserControl, 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(_browserControl, browserWrapper, TypeConversion::FromNative(download_item), callbackWrapper);
}
}
2016-03-07 12:44:49 +10:00
void ClientAdapter::OnFindResult(CefRefPtr<CefBrowser> browser, int identifier, int count, const CefRect& selectionRect, int activeMatchOrdinal, bool finalUpdate)
{
auto handler = _browserControl->FindHandler;
if (handler != nullptr)
{
auto rect = Rect(selectionRect.x, selectionRect.y, selectionRect.width, selectionRect.height);
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
2016-03-07 12:44:49 +10:00
handler->OnFindResult(_browserControl, browserWrapper, identifier, count, rect, activeMatchOrdinal, finalUpdate);
}
}
bool ClientAdapter::GetAudioParameters(CefRefPtr<CefBrowser> browser, CefAudioParameters & params)
{
auto handler = _browserControl->AudioHandler;
if (handler == nullptr)
{
return false;
}
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto parameters = new AudioParameters((CefSharp::Enums::ChannelLayout)params.channel_layout, params.sample_rate, params.frames_per_buffer);
auto result = handler->GetAudioParameters(_browserControl, browserWrapper, *parameters);
if (result)
{
params.channel_layout = (cef_channel_layout_t)parameters->ChannelLayout;
params.sample_rate = parameters->SampleRate;
params.frames_per_buffer = parameters->FramesPerBuffer;
}
return result;
}
void ClientAdapter::OnAudioStreamStarted(CefRefPtr<CefBrowser> browser, const CefAudioParameters& params, int channels)
{
auto handler = _browserControl->AudioHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
AudioParameters parameters((CefSharp::Enums::ChannelLayout)params.channel_layout, params.sample_rate, params.frames_per_buffer);
handler->OnAudioStreamStarted(_browserControl, browserWrapper, parameters, channels);
}
}
void ClientAdapter::OnAudioStreamPacket(CefRefPtr<CefBrowser> browser, const float** data, int frames, int64_t pts)
{
auto handler = _browserControl->AudioHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnAudioStreamPacket(_browserControl, browserWrapper, IntPtr((void *)data), frames, pts);
}
}
void ClientAdapter::OnAudioStreamStopped(CefRefPtr<CefBrowser> browser)
{
auto handler = _browserControl->AudioHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnAudioStreamStopped(_browserControl, browserWrapper);
}
}
void ClientAdapter::OnAudioStreamError(CefRefPtr<CefBrowser> browser, const CefString& message)
{
auto handler = _browserControl->AudioHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnAudioStreamError(_browserControl, browserWrapper, StringUtils::ToClr(message));
}
}
void ClientAdapter::OnFrameCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame)
{
auto handler = _browserControl->FrameHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto frameWrapper = gcnew CefFrameWrapper(frame);
if (browserWrapper == nullptr)
{
// Very first OnFrameCreated called may happen before OnAfterCreated
// so we have to create a new wrapper that's lifespan is scoped to this single call.
CefBrowserWrapper browserWrapper(browser);
handler->OnFrameCreated(_browserControl, %browserWrapper, frameWrapper);
}
else
{
handler->OnFrameCreated(_browserControl, browserWrapper, frameWrapper);
}
}
}
void ClientAdapter::OnFrameAttached(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, bool reattached)
{
auto handler = _browserControl->FrameHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
handler->OnFrameAttached(_browserControl, browserWrapper, % frameWrapper, reattached);
}
}
void ClientAdapter::OnFrameDetached(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame)
{
auto handler = _browserControl->FrameHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
handler->OnFrameDetached(_browserControl, browserWrapper, % frameWrapper);
}
}
void ClientAdapter::OnMainFrameChanged(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> oldFrame, CefRefPtr<CefFrame> newFrame)
{
auto handler = _browserControl->FrameHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper^ oldFrameWrapper = nullptr;
if (oldFrame.get())
{
oldFrameWrapper = gcnew CefFrameWrapper(oldFrame);
}
CefFrameWrapper^ newFrameWrapper = nullptr;
if (newFrame.get())
{
newFrameWrapper = gcnew CefFrameWrapper(newFrame);
}
handler->OnMainFrameChanged(_browserControl, browserWrapper, oldFrameWrapper, newFrameWrapper);
delete oldFrameWrapper;
delete newFrameWrapper;
}
}
bool ClientAdapter::OnShowPermissionPrompt(CefRefPtr<CefBrowser> browser, uint64_t prompt_id,
const CefString& requesting_origin, uint32_t requested_permissions,
CefRefPtr<CefPermissionPromptCallback> callback)
{
auto handler = _browserControl->PermissionHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
auto callbackWrapper = gcnew CefPermissionPromptCallbackWrapper(callback);
return handler->OnShowPermissionPrompt(_browserControl, browserWrapper, prompt_id, StringUtils::ToClr(requesting_origin), (PermissionRequestType)requested_permissions, callbackWrapper);
}
return false;
}
void ClientAdapter::OnDismissPermissionPrompt(CefRefPtr<CefBrowser> browser, uint64_t prompt_id,
cef_permission_request_result_t result)
{
auto handler = _browserControl->PermissionHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
handler->OnDismissPermissionPrompt(_browserControl, browserWrapper, prompt_id, (PermissionRequestResult)result);
}
}
bool ClientAdapter::OnRequestMediaAccessPermission(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
const CefString& requesting_origin, uint32_t requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback)
{
auto handler = _browserControl->PermissionHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
auto callbackWrapper = gcnew CefMediaAccessCallbackWrapper(callback);
return handler->OnRequestMediaAccessPermission(_browserControl, browserWrapper, %frameWrapper, StringUtils::ToClr(requesting_origin), (MediaAccessPermissionType)requested_permissions, callbackWrapper);
}
return false;
}
bool ClientAdapter::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
{
if (_disposed)
{
return true;
}
auto handled = false;
auto name = message->GetName();
2015-07-14 10:59:10 +02:00
auto argList = message->GetArgumentList();
//TODO: JSB Rename messages (remove Root from name)
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
if (name == kJavascriptRootObjectRequest)
{
auto browserAdapter = _browserAdapter;
if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed)
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
{
return true;
}
auto objectRepository = browserAdapter->JavascriptObjectRepository;
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
if (objectRepository == nullptr)
{
return true;
}
auto callbackId = GetInt64(argList, 0);
auto objectNames = argList->GetList(1);
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
auto names = gcnew List<String^>(objectNames->GetSize());
for (size_t i = 0; i < objectNames->GetSize(); i++)
{
names->Add(StringUtils::ToClr(objectNames->GetString(i)));
}
//Call GetObjects with the list of names provided (will default to all if the list is empty
//Previously we only sent a response if there were bound objects, now we always send
//a response so the promise is resolved.
auto objs = objectRepository->GetObjects(names);
auto msg = CefProcessMessage::Create(kJavascriptRootObjectResponse);
auto responseArgList = msg->GetArgumentList();
SetInt64(responseArgList, 0, callbackId);
SerializeJsObjects(objs, responseArgList, 1);
frame->SendProcessMessage(CefProcessId::PID_RENDERER, msg);
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
handled = true;
}
else if (name == kJavascriptObjectsBoundInJavascript)
{
auto browserAdapter = _browserAdapter;
if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed)
{
return true;
}
auto objectRepository = browserAdapter->JavascriptObjectRepository;
if (objectRepository == nullptr)
{
return true;
}
auto boundObjects = argList->GetList(0);
auto objs = gcnew List<Tuple<String^, bool, bool>^>(boundObjects->GetSize());
for (size_t i = 0; i < boundObjects->GetSize(); i++)
{
auto obj = boundObjects->GetDictionary(i);
auto objectName = obj->GetString("Name");
auto alreadyBound = obj->GetBool("AlreadyBound");
auto isCached = obj->GetBool("IsCached");
objs->Add(Tuple::Create(StringUtils::ToClr(objectName), alreadyBound, isCached));
}
objectRepository->ObjectsBound(objs);
handled = true;
}
Implement Javascript Binding v2 (#2247) * JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See https://github.com/cefsharp/CefSharp/issues/2246 for details
2018-01-22 10:24:25 +10:00
else if (name == kOnContextCreatedRequest)
{
//In certain circumstances the frame has already been destroyed by the time
//we get here, only continue if we have a valid frame reference
if (frame.get() && frame->IsValid())
{
if (frame->IsMain())
{
_browserControl->SetCanExecuteJavascriptOnMainFrame(frame->GetIdentifier(), true);
}
auto handler = _browserControl->RenderProcessMessageHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
handler->OnContextCreated(_browserControl, browserWrapper, %frameWrapper);
}
}
handled = true;
}
else if (name == kOnContextReleasedRequest)
{
//In certain circumstances the frame has already been destroyed by the time
//we get here, only continue if we have a valid frame reference
if (frame.get() && frame->IsValid())
{
if (frame->IsMain())
{
_browserControl->SetCanExecuteJavascriptOnMainFrame(frame->GetIdentifier(), false);
}
auto handler = _browserControl->RenderProcessMessageHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
handler->OnContextReleased(_browserControl, browserWrapper, %frameWrapper);
}
}
handled = true;
}
else if (name == kOnFocusedNodeChanged)
{
auto handler = _browserControl->RenderProcessMessageHandler;
if (handler != nullptr)
{
IDomNode^ node = nullptr;
// 0: is a node (bool)
// 1: tag name (string)
// 2: attributes (dictionary)
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
auto notEmpty = argList->GetBool(0);
if (notEmpty)
{
// Node information was passed from the render process.
auto tagName = StringUtils::ToClr(argList->GetString(1));
auto argAttributes = argList->GetDictionary(2);
auto attributes = gcnew System::Collections::Generic::Dictionary<String^, String^>();
CefDictionaryValue::KeyList keys;
argAttributes->GetKeys(keys);
for (auto key : keys)
{
attributes->Add(StringUtils::ToClr(key), StringUtils::ToClr(argAttributes->GetString(key)));
}
node = gcnew DomNode(tagName, attributes);
}
// DomNode will be empty if input focus was cleared
handler->OnFocusedNodeChanged(_browserControl, browserWrapper, %frameWrapper, node);
}
}
else if (name == kOnUncaughtException)
{
auto handler = _browserControl->RenderProcessMessageHandler;
if (handler != nullptr)
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
auto exception = gcnew JavascriptException();
exception->Message = StringUtils::ToClr(argList->GetString(0));
auto stackTrace = gcnew System::Collections::Generic::List<JavascriptStackFrame^>();
auto argFrames = argList->GetList(1);
for (auto i = 0; i < static_cast<int>(argFrames->GetSize()); i++)
{
auto argFrame = argFrames->GetList(i);
auto stackFrame = gcnew JavascriptStackFrame();
stackFrame->FunctionName = StringUtils::ToClr(argFrame->GetString(0));
stackFrame->LineNumber = argFrame->GetInt(1);
stackFrame->ColumnNumber = argFrame->GetInt(2);
stackFrame->SourceName = StringUtils::ToClr(argFrame->GetString(3));
stackTrace->Add(stackFrame);
}
exception->StackTrace = stackTrace->ToArray();
handler->OnUncaughtException(_browserControl, browserWrapper, %frameWrapper, exception);
}
}
else if (name == kEvaluateJavascriptResponse || name == kJavascriptCallbackResponse)
{
auto browserAdapter = _browserAdapter;
if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed)
{
return true;
}
auto callbackFactory = browserAdapter->JavascriptCallbackFactory;
auto success = argList->GetBool(0);
auto callbackId = GetInt64(argList, 1);
auto pendingTask = name == kEvaluateJavascriptResponse ?
_pendingTaskRepository->RemovePendingTask(callbackId) :
_pendingTaskRepository->RemoveJavascriptCallbackPendingTask(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->TrySetResult(response);
}
handled = true;
}
else if (name == kJavascriptAsyncMethodCallRequest)
2015-07-14 10:59:10 +02:00
{
auto browserAdapter = _browserAdapter;
if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed)
{
return true;
}
auto callbackFactory = browserAdapter->JavascriptCallbackFactory;
auto methodRunnerQueue = browserAdapter->MethodRunnerQueue;
//Dispose is called on a different thread, so there's a chance
//dispose is called after our IsDisposed checks, make sure we have
//actual references.
if (callbackFactory == nullptr || methodRunnerQueue == nullptr)
{
return true;
}
auto frameId = frame->GetIdentifier();
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(browser->GetIdentifier(), frameId, objectId, methodName, (callbackId > 0 ? Nullable<int64_t>(callbackId) : Nullable<int64_t>()));
for (auto i = 0; i < static_cast<int>(arguments->GetSize()); i++)
2015-07-14 10:59:10 +02:00
{
methodInvocation->Parameters->Add(DeserializeObject(arguments, i, callbackFactory));
2015-07-14 10:59:10 +02:00
}
methodRunnerQueue->Enqueue(methodInvocation);
2015-07-14 10:59:10 +02:00
handled = true;
}
else if (name == kJavascriptMessageReceived)
{
auto browserAdapter = _browserAdapter;
if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed)
{
return true;
}
auto callbackFactory = browserAdapter->JavascriptCallbackFactory;
//In certain circumstances the frame has already been destroyed by the time
//we get here, only continue if we have a valid frame reference
if (frame.get() && frame->IsValid())
{
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
CefFrameWrapper frameWrapper(frame);
auto deserializedMessage = DeserializeObject(argList, 0, callbackFactory);
_browserControl->SetJavascriptMessageReceived(gcnew JavascriptMessageReceivedEventArgs(browserWrapper, %frameWrapper, deserializedMessage));
}
handled = true;
}
return handled;
}
PendingTaskRepository<JavascriptResponse^>^ ClientAdapter::GetPendingTaskRepository()
{
return _pendingTaskRepository;
}
void ClientAdapter::MethodInvocationComplete(MethodInvocationResult^ result)
{
auto browser = GetBrowserWrapper(result->BrowserId);
if (result->CallbackId.HasValue && browser != nullptr && !browser->IsDisposed)
{
auto wrapper = static_cast<CefBrowserWrapper^>(browser);
if (wrapper == nullptr)
{
return;
}
auto cefBrowser = wrapper->Browser;
if (cefBrowser.get())
{
auto frame = cefBrowser->GetFrame(result->FrameId);
if (frame.get() && frame->IsValid())
{
auto message = CefProcessMessage::Create(kJavascriptAsyncMethodCallResponse);
auto argList = message->GetArgumentList();
SetInt64(argList, 0, result->CallbackId.Value);
argList->SetBool(1, result->Success);
if (result->Success)
{
SerializeV8Object(argList, 2, result->Result, result->NameConverter);
}
else
{
argList->SetString(2, StringUtils::ToNative(result->Message));
}
frame->SendProcessMessage(CefProcessId::PID_RENDERER, message);
}
}
}
}
2014-03-09 13:49:35 +01:00
}
}