mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
- Fix bug in CefV8Value handling of weak references. (issue #72)
- Reintroduce support for CefHandler::HandleJSBinding(). (issue #72) git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@100 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
173
tests/cefclient/binding_test.cpp
Normal file
173
tests/cefclient/binding_test.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "binding_test.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
// Implementation of the V8 handler class for the "window.cef_test.Dump"
|
||||
// function.
|
||||
class ClientV8FunctionHandler : public CefThreadSafeBase<CefV8Handler>
|
||||
{
|
||||
public:
|
||||
ClientV8FunctionHandler() {}
|
||||
virtual ~ClientV8FunctionHandler() {}
|
||||
|
||||
// Execute with the specified argument list and return value. Return true if
|
||||
// the method was handled.
|
||||
virtual bool Execute(const std::wstring& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
std::wstring& exception)
|
||||
{
|
||||
if(name == L"Dump")
|
||||
{
|
||||
// The "Dump" function will return a human-readable dump of the input
|
||||
// arguments.
|
||||
std::wstringstream stream;
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
stream << L"arg[" << i << L"] = ";
|
||||
PrintValue(arguments[i], stream, 0);
|
||||
stream << L"\n";
|
||||
}
|
||||
|
||||
retval = CefV8Value::CreateString(stream.str());
|
||||
return true;
|
||||
}
|
||||
else if(name == L"Call")
|
||||
{
|
||||
// The "Call" function will execute a function to get an object and then
|
||||
// return the result of calling a function belonging to that object. The
|
||||
// first arument is the function that will return an object and the second
|
||||
// argument is the function that will be called on that returned object.
|
||||
int argSize = arguments.size();
|
||||
if(argSize < 2 || !arguments[0]->IsFunction()
|
||||
|| !arguments[1]->IsString())
|
||||
return false;
|
||||
|
||||
CefV8ValueList argList;
|
||||
|
||||
// Execute the function stored in the first argument to retrieve an
|
||||
// object.
|
||||
CefRefPtr<CefV8Value> objectPtr;
|
||||
if(!arguments[0]->ExecuteFunction(object, argList, objectPtr, exception))
|
||||
return false;
|
||||
// Verify that the returned value is an object.
|
||||
if(!objectPtr.get() || !objectPtr->IsObject())
|
||||
return false;
|
||||
|
||||
// Retrieve the member function specified by name in the second argument
|
||||
// from the object.
|
||||
CefRefPtr<CefV8Value> funcPtr =
|
||||
objectPtr->GetValue(arguments[1]->GetStringValue());
|
||||
// Verify that the returned value is a function.
|
||||
if(!funcPtr.get() || !funcPtr->IsFunction())
|
||||
return false;
|
||||
|
||||
// Pass any additional arguments on to the member function.
|
||||
for(int i = 2; i < argSize; ++i)
|
||||
argList.push_back(arguments[i]);
|
||||
|
||||
// Execute the member function.
|
||||
return funcPtr->ExecuteFunction(arguments[0], argList, retval, exception);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Simple function for formatted output of a V8 value.
|
||||
void PrintValue(CefRefPtr<CefV8Value> value, std::wstringstream &stream,
|
||||
int indent)
|
||||
{
|
||||
std::wstringstream indent_stream;
|
||||
for(int i = 0; i < indent; ++i)
|
||||
indent_stream << L" ";
|
||||
std::wstring indent_str = indent_stream.str();
|
||||
|
||||
if(value->IsUndefined())
|
||||
stream << L"(undefined)";
|
||||
else if(value->IsNull())
|
||||
stream << L"(null)";
|
||||
else if(value->IsBool())
|
||||
stream << L"(bool) " << (value->GetBoolValue() ? L"true" : L"false");
|
||||
else if(value->IsInt())
|
||||
stream << L"(int) " << value->GetIntValue();
|
||||
else if(value->IsDouble())
|
||||
stream << L"(double) " << value->GetDoubleValue();
|
||||
else if(value->IsString())
|
||||
stream << L"(string) " << value->GetStringValue().c_str();
|
||||
else if(value->IsFunction())
|
||||
stream << L"(function) " << value->GetFunctionName().c_str();
|
||||
else if(value->IsArray()) {
|
||||
stream << L"(array) [";
|
||||
int len = value->GetArrayLength();
|
||||
for(int i = 0; i < len; ++i) {
|
||||
stream << L"\n " << indent_str.c_str() << i << L" = ";
|
||||
PrintValue(value->GetValue(i), stream, indent+1);
|
||||
}
|
||||
stream << L"\n" << indent_str.c_str() << L"]";
|
||||
} else if(value->IsObject()) {
|
||||
stream << L"(object) [";
|
||||
std::vector<std::wstring> keys;
|
||||
if(value->GetKeys(keys)) {
|
||||
for(size_t i = 0; i < keys.size(); ++i) {
|
||||
stream << L"\n " << indent_str.c_str() << keys[i].c_str() << L" = ";
|
||||
PrintValue(value->GetValue(keys[i]), stream, indent+1);
|
||||
}
|
||||
}
|
||||
stream << L"\n" << indent_str.c_str() << L"]";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void InitBindingTest(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object)
|
||||
{
|
||||
// Create the new V8 object.
|
||||
CefRefPtr<CefV8Value> testObjPtr = CefV8Value::CreateObject(NULL);
|
||||
// Add the new V8 object to the global window object with the name
|
||||
// "cef_test".
|
||||
object->SetValue(L"cef_test", testObjPtr);
|
||||
|
||||
// Create an instance of ClientV8FunctionHandler as the V8 handler.
|
||||
CefRefPtr<CefV8Handler> handlerPtr = new ClientV8FunctionHandler();
|
||||
|
||||
// Add a new V8 function to the cef_test object with the name "Dump".
|
||||
testObjPtr->SetValue(L"Dump",
|
||||
CefV8Value::CreateFunction(L"Dump", handlerPtr));
|
||||
// Add a new V8 function to the cef_test object with the name "Call".
|
||||
testObjPtr->SetValue(L"Call",
|
||||
CefV8Value::CreateFunction(L"Call", handlerPtr));
|
||||
}
|
||||
|
||||
void RunBindingTest(CefRefPtr<CefBrowser> browser)
|
||||
{
|
||||
std::wstring html =
|
||||
L"<html><body>ClientV8FunctionHandler says:<br><pre>"
|
||||
L"<script language=\"JavaScript\">"
|
||||
L"document.writeln(window.cef_test.Dump(false, 1, 7.6654,'bar',"
|
||||
L" [false,true],[5, 7.654, 1, 'foo', [true, 'bar'], 8]));"
|
||||
L"document.writeln(window.cef_test.Dump(cef));"
|
||||
L"document.writeln("
|
||||
L" window.cef_test.Call(cef.test.test_object, 'GetMessage'));"
|
||||
L"function my_object() {"
|
||||
L" var obj = {};"
|
||||
L" (function() {"
|
||||
L" obj.GetMessage = function(a) {"
|
||||
L" return 'Calling a function with value '+a+' on a user object succeeded.';"
|
||||
L" };"
|
||||
L" })();"
|
||||
L" return obj;"
|
||||
L"};"
|
||||
L"document.writeln("
|
||||
L" window.cef_test.Call(my_object, 'GetMessage', 'foobar'));"
|
||||
L"</script>"
|
||||
L"</pre></body></html>";
|
||||
browser->GetMainFrame()->LoadString(html, L"about:blank");
|
||||
}
|
14
tests/cefclient/binding_test.h
Normal file
14
tests/cefclient/binding_test.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#include "include/cef.h"
|
||||
|
||||
// Add the V8 bindings.
|
||||
void InitBindingTest(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object);
|
||||
|
||||
// Run the test.
|
||||
void RunBindingTest(CefRefPtr<CefBrowser> browser);
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "cefclient.h"
|
||||
#include "binding_test.h"
|
||||
#include "extension_test.h"
|
||||
#include "plugin_test.h"
|
||||
#include "resource_util.h"
|
||||
@@ -505,6 +506,18 @@ public:
|
||||
return RV_CONTINUE;
|
||||
}
|
||||
|
||||
// Event called for binding to a frame's JavaScript global object. The
|
||||
// return value is currently ignored.
|
||||
virtual RetVal HandleJSBinding(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object)
|
||||
{
|
||||
// Add the V8 bindings.
|
||||
InitBindingTest(browser, frame, object);
|
||||
|
||||
return RV_HANDLED;
|
||||
}
|
||||
|
||||
// Called just before a window is closed. The return value is currently
|
||||
// ignored.
|
||||
virtual RetVal HandleBeforeWindowClose(CefRefPtr<CefBrowser> browser)
|
||||
@@ -1013,7 +1026,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
#endif // !TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
}
|
||||
return 0;
|
||||
case ID_TESTS_JAVASCRIPT_HANDLER: // Test the V8 extension handler
|
||||
case ID_TESTS_JAVASCRIPT_BINDING: // Test the V8 binding handler
|
||||
if(browser.get())
|
||||
RunBindingTest(browser);
|
||||
return 0;
|
||||
case ID_TESTS_JAVASCRIPT_EXTENSION: // Test the V8 extension handler
|
||||
if(browser.get())
|
||||
RunExtensionTest(browser);
|
||||
return 0;
|
||||
|
@@ -65,7 +65,8 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "Get Source", ID_TESTS_GETSOURCE
|
||||
MENUITEM "Get Text", ID_TESTS_GETTEXT
|
||||
MENUITEM "JavaScript Extension Handler",ID_TESTS_JAVASCRIPT_HANDLER
|
||||
MENUITEM "JavaScript Binding Handler", ID_TESTS_JAVASCRIPT_BINDING
|
||||
MENUITEM "JavaScript Extension Handler",ID_TESTS_JAVASCRIPT_EXTENSION
|
||||
MENUITEM "JavaScript Execute", ID_TESTS_JAVASCRIPT_EXECUTE
|
||||
MENUITEM "Plugin", ID_TESTS_PLUGIN
|
||||
MENUITEM "Popup Window", ID_TESTS_POPUP
|
||||
|
@@ -26,13 +26,14 @@
|
||||
#define ID_PRINT 32002
|
||||
#define ID_TESTS_GETSOURCE 32769
|
||||
#define ID_TESTS_GETTEXT 32770
|
||||
#define ID_TESTS_JAVASCRIPT_HANDLER 32771
|
||||
#define ID_TESTS_JAVASCRIPT_EXECUTE 32772
|
||||
#define ID_TESTS_PLUGIN 32773
|
||||
#define ID_TESTS_POPUP 32774
|
||||
#define ID_TESTS_REQUEST 32775
|
||||
#define ID_TESTS_SCHEME_HANDLER 32776
|
||||
#define ID_TESTS_UIAPP 32777
|
||||
#define ID_TESTS_JAVASCRIPT_BINDING 32771
|
||||
#define ID_TESTS_JAVASCRIPT_EXTENSION 32772
|
||||
#define ID_TESTS_JAVASCRIPT_EXECUTE 32773
|
||||
#define ID_TESTS_PLUGIN 32774
|
||||
#define ID_TESTS_POPUP 32775
|
||||
#define ID_TESTS_REQUEST 32776
|
||||
#define ID_TESTS_SCHEME_HANDLER 32777
|
||||
#define ID_TESTS_UIAPP 32778
|
||||
#define IDC_STATIC -1
|
||||
#define IDS_LOGO 1000
|
||||
#define IDS_UIPLUGIN 1001
|
||||
|
@@ -175,6 +175,13 @@ public:
|
||||
return RV_CONTINUE;
|
||||
}
|
||||
|
||||
virtual RetVal HandleJSBinding(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object)
|
||||
{
|
||||
return RV_CONTINUE;
|
||||
}
|
||||
|
||||
virtual RetVal HandleBeforeWindowClose(CefRefPtr<CefBrowser> browser)
|
||||
{
|
||||
Lock();
|
||||
|
@@ -215,12 +215,18 @@ public:
|
||||
class V8TestHandler : public TestHandler
|
||||
{
|
||||
public:
|
||||
V8TestHandler() {}
|
||||
V8TestHandler(bool bindingTest) { binding_test_ = bindingTest; }
|
||||
|
||||
virtual void RunTest()
|
||||
{
|
||||
// extension uses a global object
|
||||
std::string object = "test";
|
||||
std::string object;
|
||||
if(binding_test_) {
|
||||
// binding uses the window object
|
||||
object = "window.test";
|
||||
} else {
|
||||
// extension uses a global object
|
||||
object = "test";
|
||||
}
|
||||
|
||||
std::stringstream testHtml;
|
||||
testHtml <<
|
||||
@@ -247,8 +253,75 @@ public:
|
||||
DestroyTest();
|
||||
return RV_CONTINUE;
|
||||
}
|
||||
|
||||
virtual RetVal HandleJSBinding(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object)
|
||||
{
|
||||
if(binding_test_) {
|
||||
TestHandleJSBinding(browser, frame, object);
|
||||
return RV_HANDLED;
|
||||
}
|
||||
return RV_CONTINUE;
|
||||
}
|
||||
|
||||
void TestHandleJSBinding(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Value> object)
|
||||
{
|
||||
// Create the new V8 object
|
||||
CefRefPtr<CefV8Value> testObj = CefV8Value::CreateObject(NULL);
|
||||
ASSERT_TRUE(testObj.get() != NULL);
|
||||
ASSERT_TRUE(object->SetValue(L"test", testObj));
|
||||
|
||||
// Create an instance of V8ExecuteV8Handler
|
||||
CefRefPtr<CefV8Handler> testHandler(new V8TestV8Handler(true));
|
||||
ASSERT_TRUE(testHandler.get() != NULL);
|
||||
|
||||
// Add the functions
|
||||
CefRefPtr<CefV8Value> testFunc;
|
||||
testFunc = CefV8Value::CreateFunction(L"execute", testHandler);
|
||||
ASSERT_TRUE(testFunc.get() != NULL);
|
||||
ASSERT_TRUE(testObj->SetValue(L"execute", testFunc));
|
||||
testFunc = CefV8Value::CreateFunction(L"execute2", testHandler);
|
||||
ASSERT_TRUE(testFunc.get() != NULL);
|
||||
ASSERT_TRUE(testObj->SetValue(L"execute2", testFunc));
|
||||
|
||||
// Add the values
|
||||
ASSERT_TRUE(testObj->SetValue(L"intVal",
|
||||
CefV8Value::CreateInt(12)));
|
||||
ASSERT_TRUE(testObj->SetValue(L"doubleVal",
|
||||
CefV8Value::CreateDouble(5.432)));
|
||||
ASSERT_TRUE(testObj->SetValue(L"boolVal",
|
||||
CefV8Value::CreateBool(true)));
|
||||
ASSERT_TRUE(testObj->SetValue(L"stringVal",
|
||||
CefV8Value::CreateString(L"the string")));
|
||||
|
||||
CefRefPtr<CefV8Value> testArray(CefV8Value::CreateArray());
|
||||
ASSERT_TRUE(testArray.get() != NULL);
|
||||
ASSERT_TRUE(testObj->SetValue(L"arrayVal", testArray));
|
||||
ASSERT_TRUE(testArray->SetValue(0, CefV8Value::CreateInt(4)));
|
||||
ASSERT_TRUE(testArray->SetValue(1, CefV8Value::CreateDouble(120.43)));
|
||||
ASSERT_TRUE(testArray->SetValue(2, CefV8Value::CreateBool(true)));
|
||||
ASSERT_TRUE(testArray->SetValue(3, CefV8Value::CreateString(L"a string")));
|
||||
}
|
||||
|
||||
bool binding_test_;
|
||||
};
|
||||
|
||||
// Verify window binding
|
||||
TEST(V8Test, Binding)
|
||||
{
|
||||
g_V8TestV8HandlerExecuteCalled = false;
|
||||
g_V8TestV8HandlerExecute2Called = false;
|
||||
|
||||
CefRefPtr<V8TestHandler> handler = new V8TestHandler(true);
|
||||
handler->ExecuteTest();
|
||||
|
||||
ASSERT_TRUE(g_V8TestV8HandlerExecuteCalled);
|
||||
ASSERT_TRUE(g_V8TestV8HandlerExecute2Called);
|
||||
}
|
||||
|
||||
// Verify extensions
|
||||
TEST(V8Test, Extension)
|
||||
{
|
||||
@@ -271,7 +344,7 @@ TEST(V8Test, Extension)
|
||||
L"})();";
|
||||
CefRegisterExtension(L"v8/test", extensionCode, new V8TestV8Handler(false));
|
||||
|
||||
CefRefPtr<V8TestHandler> handler = new V8TestHandler();
|
||||
CefRefPtr<V8TestHandler> handler = new V8TestHandler(false);
|
||||
handler->ExecuteTest();
|
||||
|
||||
ASSERT_TRUE(g_V8TestV8HandlerExecuteCalled);
|
||||
|
Reference in New Issue
Block a user