| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,11 +25,11 @@ namespace CefSharp | |||
| 25 | 25 | { | |
| 26 | 26 | private: | |
| 27 | 27 | gcroot<RegisterBoundObjectRegistry^> _callbackRegistry; | |
| 28 | - gcroot<Dictionary<String^, JavascriptObject^>^> _javascriptObjects; | ||
| 28 | + gcroot<IDictionary<String^, JavascriptObject^>^> _javascriptObjects; | ||
| 29 | 29 | gcroot<CefBrowserWrapper^> _browserWrapper; | |
| 30 | 30 | ||
| 31 | 31 | public: | |
| 32 | - BindObjectAsyncHandler(RegisterBoundObjectRegistry^ callbackRegistery, Dictionary<String^, JavascriptObject^>^ javascriptObjects, CefBrowserWrapper^ browserWrapper) | ||
| 32 | + BindObjectAsyncHandler(RegisterBoundObjectRegistry^ callbackRegistery, IDictionary<String^, JavascriptObject^>^ javascriptObjects, CefBrowserWrapper^ browserWrapper) | ||
| 33 | 33 | { | |
| 34 | 34 | _callbackRegistry = callbackRegistery; | |
| 35 | 35 | _javascriptObjects = javascriptObjects; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -82,20 +82,7 @@ namespace CefSharp | |||
| 82 | 82 | { | |
| 83 | 83 | auto javascriptObjects = DeserializeJsObjects(objects, 0); | |
| 84 | 84 | ||
| 85 | - for each (JavascriptObject ^ obj in Enumerable::OfType<JavascriptObject^>(javascriptObjects)) | ||
| 86 | - { | ||
| 87 | - //Using LegacyBinding with multiple ChromiumWebBrowser instances that share the same | ||
| 88 | - //render process and using LegacyBinding will cause problems for the limited caching implementation | ||
| 89 | - //that exists at the moment, for now we'll remove an object if already exists, same behaviour | ||
| 90 | - //as the new binding method. | ||
| 91 | - //TODO: This should be removed when https://github.com/cefsharp/CefSharp/issues/2306 | ||
| 92 | - //Is complete as objects will be stored at the browser level | ||
| 93 | - if (_javascriptObjects->ContainsKey(obj->JavascriptName)) | ||
| 94 | - { | ||
| 95 | - _javascriptObjects->Remove(obj->JavascriptName); | ||
| 96 | - } | ||
| 97 | - _javascriptObjects->Add(obj->JavascriptName, obj); | ||
| 98 | - } | ||
| 85 | + _javascriptObjectCache->InsertOrUpdate(browser->GetIdentifier(), javascriptObjects); | ||
| 99 | 86 | } | |
| 100 | 87 | } | |
| 101 | 88 | ||
@@ -118,6 +105,8 @@ namespace CefSharp | |||
| 118 | 105 | _onBrowserDestroyed->Invoke(wrapper); | |
| 119 | 106 | delete wrapper; | |
| 120 | 107 | } | |
| 108 | + | ||
| 109 | + _javascriptObjectCache->ClearCache(browser->GetIdentifier()); | ||
| 121 | 110 | }; | |
| 122 | 111 | ||
| 123 | 112 | void CefAppUnmanagedWrapper::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) | |
@@ -141,9 +130,11 @@ namespace CefSharp | |||
| 141 | 130 | ||
| 142 | 131 | if (_legacyBindingEnabled) | |
| 143 | 132 | { | |
| 144 | - if (_javascriptObjects->Count > 0 && rootObject != nullptr) | ||
| 133 | + auto values = _javascriptObjectCache->GetCacheValues(browser->GetIdentifier()); | ||
| 134 | + | ||
| 135 | + if (values->Count > 0 && rootObject != nullptr) | ||
| 145 | 136 | { | |
| 146 | - rootObject->Bind(_javascriptObjects->Values, context->GetGlobal()); | ||
| 137 | + rootObject->Bind(values, context->GetGlobal()); | ||
| 147 | 138 | } | |
| 148 | 139 | } | |
| 149 | 140 | ||
@@ -153,13 +144,14 @@ namespace CefSharp | |||
| 153 | 144 | auto global = context->GetGlobal(); | |
| 154 | 145 | auto browserWrapper = FindBrowserWrapper(browser->GetIdentifier()); | |
| 155 | 146 | auto processId = System::Diagnostics::Process::GetCurrentProcess()->Id; | |
| 147 | + auto objectCache = _javascriptObjectCache->GetCache(browser->GetIdentifier()); | ||
| 156 | 148 | ||
| 157 | 149 | //TODO: JSB: Split functions into their own classes | |
| 158 | 150 | //Browser wrapper is only used for BindObjectAsync | |
| 159 | - auto bindObjAsyncFunction = CefV8Value::CreateFunction(kBindObjectAsync, new BindObjectAsyncHandler(_registerBoundObjectRegistry, _javascriptObjects, browserWrapper)); | ||
| 160 | - auto unBindObjFunction = CefV8Value::CreateFunction(kDeleteBoundObject, new RegisterBoundObjectHandler(_javascriptObjects)); | ||
| 161 | - auto removeObjectFromCacheFunction = CefV8Value::CreateFunction(kRemoveObjectFromCache, new RegisterBoundObjectHandler(_javascriptObjects)); | ||
| 162 | - auto isObjectCachedFunction = CefV8Value::CreateFunction(kIsObjectCached, new RegisterBoundObjectHandler(_javascriptObjects)); | ||
| 151 | + auto bindObjAsyncFunction = CefV8Value::CreateFunction(kBindObjectAsync, new BindObjectAsyncHandler(_registerBoundObjectRegistry, objectCache, browserWrapper)); | ||
| 152 | + auto unBindObjFunction = CefV8Value::CreateFunction(kDeleteBoundObject, new RegisterBoundObjectHandler(objectCache)); | ||
| 153 | + auto removeObjectFromCacheFunction = CefV8Value::CreateFunction(kRemoveObjectFromCache, new RegisterBoundObjectHandler(objectCache)); | ||
| 154 | + auto isObjectCachedFunction = CefV8Value::CreateFunction(kIsObjectCached, new RegisterBoundObjectHandler(objectCache)); | ||
| 163 | 155 | auto postMessageFunction = CefV8Value::CreateFunction(kPostMessage, new JavascriptPostMessageHandler(rootObject == nullptr ? nullptr : rootObject->CallbackRegistry)); | |
| 164 | 156 | auto promiseHandlerFunction = CefV8Value::CreateFunction(kSendEvalScriptResponse, new JavascriptPromiseHandler()); | |
| 165 | 157 | ||
@@ -633,15 +625,7 @@ namespace CefSharp | |||
| 633 | 625 | auto javascriptObjects = DeserializeJsObjects(argList, 1); | |
| 634 | 626 | ||
| 635 | 627 | //Caching of JavascriptObjects | |
| 636 | - //TODO: JSB Should caching be configurable? On a per object basis? | ||
| 637 | - for each (JavascriptObject ^ obj in Enumerable::OfType<JavascriptObject^>(javascriptObjects)) | ||
| 638 | - { | ||
| 639 | - if (_javascriptObjects->ContainsKey(obj->JavascriptName)) | ||
| 640 | - { | ||
| 641 | - _javascriptObjects->Remove(obj->JavascriptName); | ||
| 642 | - } | ||
| 643 | - _javascriptObjects->Add(obj->JavascriptName, obj); | ||
| 644 | - } | ||
| 628 | + _javascriptObjectCache->InsertOrUpdate(browser->GetIdentifier(), javascriptObjects); | ||
| 645 | 629 | ||
| 646 | 630 | auto rootObject = GetJsRootObjectWrapper(browser->GetIdentifier(), frame->GetIdentifier()); | |
| 647 | 631 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -35,25 +35,33 @@ namespace CefSharp | |||
| 35 | 35 | CefString _jsBindingPropertyNameCamelCase; | |
| 36 | 36 | ||
| 37 | 37 | // The serialized registered object data waiting to be used. | |
| 38 | - gcroot<Dictionary<String^, JavascriptObject^>^> _javascriptObjects; | ||
| 38 | + gcroot<IJavaScriptObjectCache^> _javascriptObjectCache; | ||
| 39 | 39 | ||
| 40 | 40 | gcroot<RegisterBoundObjectRegistry^> _registerBoundObjectRegistry; | |
| 41 | 41 | ||
| 42 | 42 | public: | |
| 43 | 43 | static const CefString kPromiseCreatorScript; | |
| 44 | 44 | ||
| 45 | - CefAppUnmanagedWrapper(IRenderProcessHandler^ handler, List<CefCustomScheme^>^ schemes, bool enableFocusedNodeChanged, Action<CefBrowserWrapper^>^ onBrowserCreated, Action<CefBrowserWrapper^>^ onBrowserDestroyed) : SubProcessApp(schemes) | ||
| 45 | + CefAppUnmanagedWrapper(IRenderProcessHandler^ handler, List<CefCustomScheme^>^ schemes, bool jsbCachePerBrowser, bool enableFocusedNodeChanged, Action<CefBrowserWrapper^>^ onBrowserCreated, Action<CefBrowserWrapper^>^ onBrowserDestroyed) : SubProcessApp(schemes) | ||
| 46 | 46 | { | |
| 47 | 47 | _handler = handler; | |
| 48 | 48 | _onBrowserCreated = onBrowserCreated; | |
| 49 | 49 | _onBrowserDestroyed = onBrowserDestroyed; | |
| 50 | 50 | _browserWrappers = gcnew ConcurrentDictionary<int, CefBrowserWrapper^>(); | |
| 51 | 51 | _focusedNodeChangedEnabled = enableFocusedNodeChanged; | |
| 52 | - _javascriptObjects = gcnew Dictionary<String^, JavascriptObject^>(); | ||
| 53 | 52 | _registerBoundObjectRegistry = gcnew RegisterBoundObjectRegistry(); | |
| 54 | 53 | _legacyBindingEnabled = false; | |
| 55 | 54 | _jsBindingPropertyName = "CefSharp"; | |
| 56 | 55 | _jsBindingPropertyNameCamelCase = "cefSharp"; | |
| 56 | + | ||
| 57 | + if (jsbCachePerBrowser) | ||
| 58 | + { | ||
| 59 | + _javascriptObjectCache = gcnew PerBrowserJavaScriptObjectCache(); | ||
| 60 | + } | ||
| 61 | + else | ||
| 62 | + { | ||
| 63 | + _javascriptObjectCache = gcnew LegacyJavaScriptObjectCache(); | ||
| 64 | + } | ||
| 57 | 65 | } | |
| 58 | 66 | ||
| 59 | 67 | ~CefAppUnmanagedWrapper() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,10 +27,10 @@ namespace CefSharp | |||
| 27 | 27 | private class RegisterBoundObjectHandler : public CefV8Handler | |
| 28 | 28 | { | |
| 29 | 29 | private: | |
| 30 | - gcroot<Dictionary<String^, JavascriptObject^>^> _javascriptObjects; | ||
| 30 | + gcroot<IDictionary<String^, JavascriptObject^>^> _javascriptObjects; | ||
| 31 | 31 | ||
| 32 | 32 | public: | |
| 33 | - RegisterBoundObjectHandler(Dictionary<String^, JavascriptObject^>^ javascriptObjects) | ||
| 33 | + RegisterBoundObjectHandler(IDictionary<String^, JavascriptObject^>^ javascriptObjects) | ||
| 34 | 34 | { | |
| 35 | 35 | _javascriptObjects = javascriptObjects; | |
| 36 | 36 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,9 +33,10 @@ namespace CefSharp | |||
| 33 | 33 | auto onBrowserCreated = gcnew Action<CefBrowserWrapper^>(this, &SubProcess::OnBrowserCreated); | |
| 34 | 34 | auto onBrowserDestroyed = gcnew Action<CefBrowserWrapper^>(this, &SubProcess::OnBrowserDestroyed); | |
| 35 | 35 | auto schemes = CefCustomScheme::ParseCommandLineArguments(args); | |
| 36 | + auto jsbCachePerBrowser = CommandLineArgsParser::HasArgument(args, CefSharpArguments::PerBrowserJavaScriptObjectCache); | ||
| 36 | 37 | auto enableFocusedNodeChanged = CommandLineArgsParser::HasArgument(args, CefSharpArguments::FocusedNodeChangedEnabledArgument); | |
| 37 | 38 | ||
| 38 | - _cefApp = new CefAppUnmanagedWrapper(handler, schemes, enableFocusedNodeChanged, onBrowserCreated, onBrowserDestroyed); | ||
| 39 | + _cefApp = new CefAppUnmanagedWrapper(handler, schemes, jsbCachePerBrowser, enableFocusedNodeChanged, onBrowserCreated, onBrowserDestroyed); | ||
| 39 | 40 | } | |
| 40 | 41 | ||
| 41 | 42 | !SubProcess() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,118 @@ | |||
| 1 | + using System.Collections.Generic; | ||
| 2 | + using CefSharp.Internals; | ||
| 3 | + using Xunit; | ||
| 4 | + | ||
| 5 | + namespace CefSharp.Test.JavascriptBinding | ||
| 6 | + { | ||
| 7 | + public class LegacyJavaScriptObjectCacheTests | ||
| 8 | + { | ||
| 9 | + private const int BrowserId = 1; | ||
| 10 | + | ||
| 11 | + [Fact] | ||
| 12 | + public void InsertOrUpdateShouldAddObjectsToCache() | ||
| 13 | + { | ||
| 14 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 15 | + var javascriptObjects = new List<JavascriptObject> | ||
| 16 | + { | ||
| 17 | + new JavascriptObject { Name = "Object1" }, | ||
| 18 | + new JavascriptObject { Name = "Object2" } | ||
| 19 | + }; | ||
| 20 | + | ||
| 21 | + cache.InsertOrUpdate(BrowserId, javascriptObjects); | ||
| 22 | + | ||
| 23 | + var cachedValues = cache.GetCacheValues(BrowserId); | ||
| 24 | + Assert.Contains(javascriptObjects[0], cachedValues); | ||
| 25 | + Assert.Contains(javascriptObjects[1], cachedValues); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + [Fact] | ||
| 29 | + public void GetCacheValuesShouldReturnAllCachedObjects() | ||
| 30 | + { | ||
| 31 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 32 | + var javascriptObjects = new List<JavascriptObject> | ||
| 33 | + { | ||
| 34 | + new JavascriptObject { Name = "Object1" }, | ||
| 35 | + new JavascriptObject { Name = "Object2" } | ||
| 36 | + }; | ||
| 37 | + cache.InsertOrUpdate(BrowserId, javascriptObjects); | ||
| 38 | + | ||
| 39 | + var cachedValues = cache.GetCacheValues(BrowserId); | ||
| 40 | + | ||
| 41 | + Assert.Equal(2, cachedValues.Count); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + [Fact] | ||
| 45 | + public void GetCacheShouldReturnUnderlyingDictionary() | ||
| 46 | + { | ||
| 47 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 48 | + var javascriptObjects = new List<JavascriptObject> | ||
| 49 | + { | ||
| 50 | + new JavascriptObject { Name = "Object1" } | ||
| 51 | + }; | ||
| 52 | + cache.InsertOrUpdate(BrowserId, javascriptObjects); | ||
| 53 | + | ||
| 54 | + var cachedDictionary = cache.GetCache(BrowserId); | ||
| 55 | + | ||
| 56 | + Assert.Single(cachedDictionary); | ||
| 57 | + Assert.True(cachedDictionary.ContainsKey("Object1")); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + [Fact] | ||
| 61 | + public void InsertOrUpdateShouldReplaceExistingObjects() | ||
| 62 | + { | ||
| 63 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 64 | + var initialObjects = new List<JavascriptObject> | ||
| 65 | + { | ||
| 66 | + new JavascriptObject { Name = "Object1" } | ||
| 67 | + }; | ||
| 68 | + var updatedObjects = new List<JavascriptObject> | ||
| 69 | + { | ||
| 70 | + new JavascriptObject { Name = "Object1" } | ||
| 71 | + }; | ||
| 72 | + cache.InsertOrUpdate(BrowserId, initialObjects); | ||
| 73 | + | ||
| 74 | + cache.InsertOrUpdate(BrowserId, updatedObjects); | ||
| 75 | + | ||
| 76 | + var cachedValues = cache.GetCacheValues(BrowserId); | ||
| 77 | + Assert.DoesNotContain(initialObjects[0], cachedValues); | ||
| 78 | + Assert.Contains(updatedObjects[0], cachedValues); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + [Fact] | ||
| 82 | + public void InsertOrUpdateShouldAppendObjectsWithDifferentNames() | ||
| 83 | + { | ||
| 84 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 85 | + var initialObjects = new List<JavascriptObject> | ||
| 86 | + { | ||
| 87 | + new JavascriptObject { Name = "Object1" } | ||
| 88 | + }; | ||
| 89 | + var updatedObjects = new List<JavascriptObject> | ||
| 90 | + { | ||
| 91 | + new JavascriptObject { Name = "Object2" } | ||
| 92 | + }; | ||
| 93 | + cache.InsertOrUpdate(BrowserId, initialObjects); | ||
| 94 | + | ||
| 95 | + cache.InsertOrUpdate(BrowserId, updatedObjects); | ||
| 96 | + | ||
| 97 | + var cachedValues = cache.GetCacheValues(BrowserId); | ||
| 98 | + Assert.Contains(initialObjects[0], cachedValues); | ||
| 99 | + Assert.Contains(updatedObjects[0], cachedValues); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + [Fact] | ||
| 103 | + public void ClearCacheShouldDoNothing() | ||
| 104 | + { | ||
| 105 | + var cache = new LegacyJavaScriptObjectCache(); | ||
| 106 | + var javascriptObjects = new List<JavascriptObject> | ||
| 107 | + { | ||
| 108 | + new JavascriptObject { Name = "Object1" } | ||
| 109 | + }; | ||
| 110 | + cache.InsertOrUpdate(BrowserId, javascriptObjects); | ||
| 111 | + | ||
| 112 | + cache.ClearCache(BrowserId); | ||
| 113 | + | ||
| 114 | + var cachedValues = cache.GetCacheValues(BrowserId); | ||
| 115 | + Assert.Contains(javascriptObjects[0], cachedValues); | ||
| 116 | + } | ||
| 117 | + } | ||
| 118 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments