Skip to content

Commit d5d68ee

Browse files
committed
JSB Add Caching
Bound object meta data is cached within a render process CefSharp.IsObjectCached - JS method to test if object cached CefSharp.RemoveObjectFromCache - JS method to remove object from cache If a request is made for multiple objects with not all of them being cached then a IPC message is sent. When all objects already bound return response object for consistency FindBrowserWrapper signature change - it's really not safe to throw a managed exception in the middle of unmanaged code, changed to logging and null checking JavascriptObjectRepository - Add All Constant - Used when All objects are requested for binding (objects can also be requested by name) TODO: Add a JS library to improve user experience when dealing with cached objects
1 parent ecd4fd0 commit d5d68ee

File tree

5 files changed

+198
-66
lines changed

5 files changed

+198
-66
lines changed

CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.cpp

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55

66
#include "Stdafx.h"
77

8-
#include "include\base\cef_logging.h"
98
#include "CefBrowserWrapper.h"
109
#include "CefAppUnmanagedWrapper.h"
1110
#include "RegisterBoundObjectHandler.h"
1211
#include "JavascriptRootObjectWrapper.h"
1312
#include "Serialization\V8Serialization.h"
1413
#include "Serialization\JsObjectsSerialization.h"
15-
#include "Async/JavascriptAsyncMethodCallback.h"
14+
#include "Async\JavascriptAsyncMethodCallback.h"
1615
#include "..\CefSharp.Core\Internals\Messaging\Messages.h"
1716
#include "..\CefSharp.Core\Internals\Serialization\Primitives.h"
1817

18+
using namespace System;
1919
using namespace System::Diagnostics;
2020
using namespace System::Collections::Generic;
2121
using namespace CefSharp::Internals::Messaging;
@@ -75,21 +75,13 @@ namespace CefSharp
7575

7676
if (_legacyBindingEnabled)
7777
{
78-
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier(), true);
79-
80-
auto rootObjectWrappers = browserWrapper->JavascriptRootObjectWrappers;
81-
auto frameId = frame->GetIdentifier();
82-
8378
if (_javascriptObjects->Count > 0)
8479
{
85-
JavascriptRootObjectWrapper^ rootObject;
86-
if (!rootObjectWrappers->TryGetValue(frameId, rootObject))
80+
auto rootObject = GetJsRootObjectWrapper(browser->GetIdentifier(), frame->GetIdentifier());
81+
if (rootObject != nullptr)
8782
{
88-
rootObject = gcnew JavascriptRootObjectWrapper(browser->GetIdentifier(), browserWrapper->BrowserProcess);
89-
rootObjectWrappers->TryAdd(frameId, rootObject);
83+
rootObject->Bind(_javascriptObjects->Values, context->GetGlobal());
9084
}
91-
92-
rootObject->Bind(_javascriptObjects->Values, context->GetGlobal());
9385
}
9486
}
9587

@@ -98,15 +90,21 @@ namespace CefSharp
9890
auto cefSharpObj = CefV8Value::CreateObject(NULL, NULL);
9991
global->SetValue("CefSharp", cefSharpObj, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
10092

101-
auto bindObjAsyncFunction = CefV8Value::CreateFunction("BindObjectAsync", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects));
93+
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier());
94+
95+
//TODO: JSB: Split functions into their own classes
96+
//Browser wrapper is only used for BindObjectAsync
97+
auto bindObjAsyncFunction = CefV8Value::CreateFunction("BindObjectAsync", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects, browserWrapper));
10298
cefSharpObj->SetValue("BindObjectAsync", bindObjAsyncFunction, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_NONE);
10399

104-
auto unBindObFunction = CefV8Value::CreateFunction("DeleteBoundObject", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects));
100+
auto unBindObFunction = CefV8Value::CreateFunction("DeleteBoundObject", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects, nullptr));
105101
cefSharpObj->SetValue("DeleteBoundObject", unBindObFunction, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_NONE);
106102

107-
//TODO: JSB We could in theory auto bind all the cached objects which would resemble the original JSB behaviour, if
108-
//the cache is empty which would be the case for any cross-site navigation request or the first request made to a browser instance
109-
//then no objects would be bound by default
103+
auto removeObjectFromCacheFunction = CefV8Value::CreateFunction("RemoveObjectFromCache", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects, nullptr));
104+
cefSharpObj->SetValue("RemoveObjectFromCache", removeObjectFromCacheFunction, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_NONE);
105+
106+
auto isObjectCachedFunction = CefV8Value::CreateFunction("IsObjectCached", new RegisterBoundObjectHandler(_registerBoundObjectRegistry, _javascriptObjects, nullptr));
107+
cefSharpObj->SetValue("IsObjectCached", isObjectCachedFunction, CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_NONE);
110108
};
111109

112110
void CefAppUnmanagedWrapper::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
@@ -123,7 +121,13 @@ namespace CefSharp
123121
browser->SendProcessMessage(CefProcessId::PID_BROWSER, contextReleasedMessage);
124122
}
125123

126-
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier(), true);
124+
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier());
125+
126+
//If we no longer have a browser wrapper reference then there's nothing we can do
127+
if (browserWrapper == nullptr)
128+
{
129+
return;
130+
}
127131

128132
auto rootObjectWrappers = browserWrapper->JavascriptRootObjectWrappers;
129133

@@ -177,15 +181,37 @@ namespace CefSharp
177181
browser->SendProcessMessage(CefProcessId::PID_BROWSER, focusedNodeChangedMessage);
178182
}
179183

180-
CefBrowserWrapper^ CefAppUnmanagedWrapper::FindBrowserWrapper(int browserId, bool mustExist)
184+
JavascriptRootObjectWrapper^ CefAppUnmanagedWrapper::GetJsRootObjectWrapper(int browserId, int64 frameId)
185+
{
186+
auto browserWrapper = FindBrowserWrapper(browserId);
187+
188+
if (browserWrapper == nullptr)
189+
{
190+
return nullptr;
191+
}
192+
193+
auto rootObjectWrappers = browserWrapper->JavascriptRootObjectWrappers;
194+
195+
JavascriptRootObjectWrapper^ rootObject;
196+
if (!rootObjectWrappers->TryGetValue(frameId, rootObject))
197+
{
198+
rootObject = gcnew JavascriptRootObjectWrapper(browserId, browserWrapper->BrowserProcess);
199+
rootObjectWrappers->TryAdd(frameId, rootObject);
200+
}
201+
202+
return rootObject;
203+
}
204+
205+
CefBrowserWrapper^ CefAppUnmanagedWrapper::FindBrowserWrapper(int browserId)
181206
{
182207
CefBrowserWrapper^ wrapper = nullptr;
183208

184209
_browserWrappers->TryGetValue(browserId, wrapper);
185210

186-
if (mustExist && wrapper == nullptr)
211+
if (wrapper == nullptr)
187212
{
188-
throw gcnew InvalidOperationException(String::Format("Failed to identify BrowserWrapper in OnContextCreated. : {0}", browserId));
213+
//TODO: Find the syntax for delcaring the native string directly
214+
LOG(ERROR) << StringUtils::ToNative("Failed to identify BrowserWrapper in OnContextCreated BrowserId:" + browserId).ToString();
189215
}
190216

191217
return wrapper;
@@ -197,7 +223,7 @@ namespace CefSharp
197223
auto name = message->GetName();
198224
auto argList = message->GetArgumentList();
199225

200-
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier(), false);
226+
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier());
201227
//Error handling for missing/closed browser
202228
if (browserWrapper == nullptr)
203229
{
@@ -434,28 +460,25 @@ namespace CefSharp
434460
auto callbackId = GetInt64(argList, 3);
435461
auto javascriptObjects = DeserializeJsObjects(argList, 4);
436462

437-
//TODO: JSB Implement Caching of JavascriptObjects
438-
//Should caching be configurable? On a per object basis?
439-
/*for each (JavascriptObject^ obj in Enumerable::OfType<JavascriptObject^>(javascriptObjects))
463+
//Caching of JavascriptObjects
464+
//TODO: JSB Should caching be configurable? On a per object basis?
465+
for each (JavascriptObject^ obj in Enumerable::OfType<JavascriptObject^>(javascriptObjects))
440466
{
441467
if (_javascriptObjects->ContainsKey(obj->JavascriptName))
442468
{
443469
_javascriptObjects->Remove(obj->JavascriptName);
444470
}
445471
_javascriptObjects->Add(obj->JavascriptName, obj);
446-
}*/
447-
448-
auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier(), true);
472+
}
449473

450-
auto rootObjectWrappers = browserWrapper->JavascriptRootObjectWrappers;
451474
auto frame = browser->GetFrame(frameId);
452475
if (frame.get())
453476
{
454-
JavascriptRootObjectWrapper^ rootObject;
455-
if (!rootObjectWrappers->TryGetValue(frameId, rootObject))
477+
auto rootObject = GetJsRootObjectWrapper(browser->GetIdentifier(), frameId);
478+
479+
if (rootObject == nullptr)
456480
{
457-
rootObject = gcnew JavascriptRootObjectWrapper(browser->GetIdentifier(), browserWrapper->BrowserProcess);
458-
rootObjectWrappers->TryAdd(frameId, rootObject);
481+
return false;
459482
}
460483

461484
auto context = frame->GetV8Context();
@@ -472,6 +495,8 @@ namespace CefSharp
472495
//Response object has no Accessor or Interceptor
473496
auto response = CefV8Value::CreateObject(NULL, NULL);
474497

498+
response->SetValue("Count", CefV8Value::CreateInt(javascriptObjects->Count), CefV8Value::PropertyAttribute::V8_PROPERTY_ATTRIBUTE_READONLY);
499+
475500
if (javascriptObjects->Count > 0)
476501
{
477502
//TODO: JSB Should we include a list of successfully bound object names?
@@ -486,8 +511,6 @@ namespace CefSharp
486511
callback->Success(response);
487512
}
488513

489-
//TODO: JSB deal with failure - no object matching bound
490-
491514
//Send message notifying Browser Process of which objects were bound
492515
//We do this after the objects have been created in the V8Context to gurantee
493516
//they are accessible.

CefSharp.BrowserSubprocess.Core/CefAppUnmanagedWrapper.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ namespace CefSharp
6767
delete _schemes;
6868
}
6969

70-
CefBrowserWrapper^ FindBrowserWrapper(int browserId, bool mustExist);
70+
CefBrowserWrapper^ FindBrowserWrapper(int browserId);
71+
JavascriptRootObjectWrapper^ GetJsRootObjectWrapper(int browserId, int64 frameId);
7172

7273
virtual DECL CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE;
7374
virtual DECL void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;

0 commit comments

Comments
 (0)