- Add support for running unit tests without multi-threaded message loop mode (issue #338).

- Mac: Fix unit test expectations.
- Mac: cef_time_t.day_of_week is not supported.


git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@448 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-12-30 20:55:16 +00:00
parent 893176fe5a
commit 8d6c760bbd
20 changed files with 3353 additions and 39 deletions

90
cef.gyp
View File

@ -295,6 +295,7 @@
{
'target_name': 'cef_unittests',
'type': 'executable',
'mac_bundle': 1,
'msvs_guid': '8500027C-B11A-11DE-A16E-B80256D89593',
'dependencies': [
'../base/base.gyp:base',
@ -307,6 +308,8 @@
'libcef_dll_wrapper',
],
'sources': [
'tests/cefclient/cefclient_switches.cpp',
'tests/cefclient/cefclient_switches.h',
'tests/unittests/command_line_unittest.cc',
'tests/unittests/content_filter_unittest.cc',
'tests/unittests/cookie_unittest.cc',
@ -328,10 +331,97 @@
'tests/unittests/xml_reader_unittest.cc',
'tests/unittests/zip_reader_unittest.cc',
],
'mac_bundle_resources': [
'tests/unittests/mac/unittests.icns',
'tests/unittests/mac/English.lproj/InfoPlist.strings',
'tests/unittests/mac/English.lproj/MainMenu.xib',
'tests/unittests/mac/Info.plist',
],
'mac_bundle_resources!': [
# TODO(mark): Come up with a fancier way to do this (mac_info_plist?)
# that automatically sets the correct INFOPLIST_FILE setting and adds
# the file to a source group.
'tests/unittests/mac/Info.plist',
],
'xcode_settings': {
'INFOPLIST_FILE': 'tests/unittests/mac/Info.plist',
},
'include_dirs': [
'.',
'..',
],
'conditions': [
[ 'OS=="mac"', {
'product_name': 'cef_unittests',
'variables': {
'repack_path': '../tools/grit/grit/format/repack.py',
},
'actions': [
{
'action_name': 'repack_locales',
'process_outputs_as_mac_bundle_resources': 1,
'inputs': [
'tools/repack_locales.py',
# NOTE: Ideally the common command args would be shared
# amongst inputs/outputs/action, but the args include shell
# variables which need to be passed intact, and command
# expansion wants to expand the shell variables. Adding the
# explicit quoting here was the only way it seemed to work.
'>!@(<(repack_locales_cmd) -i -g \'<(grit_out_dir)\' -s \'<(SHARED_INTERMEDIATE_DIR)\' -x \'<(INTERMEDIATE_DIR)\' <(locales))',
],
'outputs': [
'>!@(<(repack_locales_cmd) -o -g \'<(grit_out_dir)\' -s \'<(SHARED_INTERMEDIATE_DIR)\' -x \'<(INTERMEDIATE_DIR)\' <(locales))',
],
'action': [
'<@(repack_locales_cmd)',
'-g', '<(grit_out_dir)',
'-s', '<(SHARED_INTERMEDIATE_DIR)',
'-x', '<(INTERMEDIATE_DIR)',
'<@(locales)',
],
},
{
'action_name': 'repack_resources',
'process_outputs_as_mac_bundle_resources': 1,
'variables': {
'pak_inputs': [
'<(grit_out_dir)/devtools_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.pak',
],
},
'inputs': [
'<(repack_path)',
'<@(pak_inputs)',
],
'outputs': [
'<(INTERMEDIATE_DIR)/repack/chrome.pak',
],
'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
},
],
'copies': [
{
# Add library dependencies to the bundle.
'destination': '<(PRODUCT_DIR)/cef_unittests.app/Contents/MacOS/',
'files': [
'<(PRODUCT_DIR)/libcef.dylib',
'<(PRODUCT_DIR)/ffmpegsumo.so',
],
},
],
'link_settings': {
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
],
},
'sources': [
'tests/unittests/run_all_unittests_mac.mm',
],
}],
],
},
{
'target_name': 'libcef',

View File

@ -44,7 +44,9 @@ typedef struct _cef_time_t
{
int year; // Four digit year "2007"
int month; // 1-based month (values 1 = January, etc.)
#if !defined(OS_MACOSX)
int day_of_week; // 0-based day of week (0 = Sunday, etc.)
#endif
int day_of_month; // 1-based day of month (1-31)
int hour; // Hour within the current day (0-23)
int minute; // Minute within the current hour (0-59)

View File

@ -789,6 +789,9 @@ void CefBrowserImpl::UIT_DestroyBrowser()
UIT_GetWebViewHost()->webwidget()->close();
webviewhost_.reset();
// Remove the reference to the window handle.
UIT_ClearMainWndHandle();
// Remove the reference added in UIT_CreateBrowser().
Release();
@ -802,7 +805,9 @@ void CefBrowserImpl::UIT_CloseBrowser()
if (IsWindowRenderingDisabled()) {
UIT_DestroyBrowser();
} else {
UIT_CloseView(UIT_GetMainWndHandle());
gfx::NativeView view = UIT_GetMainWndHandle();
if (view)
UIT_CloseView(view);
}
}

View File

@ -197,6 +197,7 @@ public:
return popuphost_->view_handle();
}
gfx::NativeView UIT_GetMainWndHandle();
void UIT_ClearMainWndHandle();
BrowserNavigationController* UIT_GetNavigationController() {
REQUIRE_UIT();

View File

@ -40,6 +40,11 @@ gfx::NativeView CefBrowserImpl::UIT_GetMainWndHandle() {
return window_info_.m_Widget;
}
void CefBrowserImpl::UIT_ClearMainWndHandle() {
REQUIRE_UIT();
window_info_.m_Widget = NULL;
}
bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
{
REQUIRE_UIT();

View File

@ -41,6 +41,11 @@ gfx::NativeView CefBrowserImpl::UIT_GetMainWndHandle() {
return window_info_.m_View;
}
void CefBrowserImpl::UIT_ClearMainWndHandle() {
REQUIRE_UIT();
window_info_.m_View = NULL;
}
bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
{
REQUIRE_UIT();

View File

@ -163,6 +163,12 @@ gfx::NativeWindow CefBrowserImpl::UIT_GetMainWndHandle() {
window_info_.m_hWndParent : window_info_.m_hWnd;
}
void CefBrowserImpl::UIT_ClearMainWndHandle() {
REQUIRE_UIT();
if (!window_info_.m_bWindowRenderingDisabled)
window_info_.m_hWnd = NULL;
}
bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
{
REQUIRE_UIT();

View File

@ -9,7 +9,9 @@ void cef_time_to_basetime(const cef_time_t& cef_time, base::Time& time)
base::Time::Exploded exploded;
exploded.year = cef_time.year;
exploded.month = cef_time.month;
#if !defined(OS_MACOSX)
exploded.day_of_week = cef_time.day_of_week;
#endif
exploded.day_of_month = cef_time.day_of_month;
exploded.hour = cef_time.hour;
exploded.minute = cef_time.minute;
@ -24,7 +26,9 @@ void cef_time_from_basetime(const base::Time& time, cef_time_t& cef_time)
time.UTCExplode(&exploded);
cef_time.year = exploded.year;
cef_time.month = exploded.month;
#if !defined(OS_MACOSX)
cef_time.day_of_week = exploded.day_of_week;
#endif
cef_time.day_of_month = exploded.day_of_month;
cef_time.hour = exploded.hour;
cef_time.minute = exploded.minute;

View File

@ -87,9 +87,9 @@ TEST(CommandLineTest, Init)
"--switch1",
"-switch2=val2",
"-switch3=val3",
"-switch4=\"val 4\"",
"-switch4=val 4",
"arg1",
"\"arg 2\""
"arg 2"
};
command_line->InitFromArgv(sizeof(args) / sizeof(char*), args);
#endif

View File

@ -76,7 +76,9 @@ void CreateCookie(CefCookie& cookie, bool withDomain,
cookie.has_expires = true;
cookie.expires.year = 2200;
cookie.expires.month = 4;
#if !defined(OS_MACOSX)
cookie.expires.day_of_week = 5;
#endif
cookie.expires.day_of_month = 11;
CookieVector cookies;
@ -114,7 +116,9 @@ void GetCookie(const CefCookie& cookie, bool withDomain,
EXPECT_TRUE(cookie_read.has_expires);
EXPECT_EQ(cookie.expires.year, cookie_read.expires.year);
EXPECT_EQ(cookie.expires.month, cookie_read.expires.month);
#if !defined(OS_MACOSX)
EXPECT_EQ(cookie.expires.day_of_week, cookie_read.expires.day_of_week);
#endif
EXPECT_EQ(cookie.expires.day_of_month, cookie_read.expires.day_of_month);
EXPECT_EQ(cookie.expires.hour, cookie_read.expires.hour);
EXPECT_EQ(cookie.expires.minute, cookie_read.expires.minute);

View File

@ -0,0 +1,3 @@
/* Localized versions of Info.plist keys */
NSHumanReadableCopyright = "© Chromium Embedded Framework Authors, 2010";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>unittests.icns</string>
<key>CFBundleIdentifier</key>
<string>org.cef.unittests</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Binary file not shown.

View File

@ -1,9 +1,103 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2011 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 "test_suite.h"
#include "include/cef_app.h"
#include "include/cef_task.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/threading/thread.h"
namespace {
// Thread used to run the test suite.
class CefTestThread : public base::Thread {
public:
CefTestThread(CefTestSuite* test_suite)
: base::Thread("test_thread"),
test_suite_(test_suite)
{
}
void RunTests() {
// Run the test suite.
retval_ = test_suite_->Run();
// Quit the CEF message loop.
class QuitTask : public CefTask
{
public:
QuitTask() {}
virtual void Execute(CefThreadId threadId) { CefQuitMessageLoop(); }
IMPLEMENT_REFCOUNTING(QuitTask);
};
CefPostTask(TID_UI, new QuitTask());
}
int retval() { return retval_; }
protected:
CefTestSuite* test_suite_;
int retval_;
};
} // namespace
int main(int argc, char** argv) {
return CefTestSuite(argc, argv).Run();
// Initialize the CommandLine object.
CefTestSuite::InitCommandLine(argc, argv);
CefSettings settings;
CefTestSuite::GetSettings(settings);
#if defined(OS_MACOSX)
// Platform-specific initialization.
extern void PlatformInit();
PlatformInit();
#endif
// Initialize CEF.
CefInitialize(settings, NULL);
// Create the test suite object.
CefTestSuite test_suite(argc, argv);
int retval;
if (settings.multi_threaded_message_loop) {
// Run the test suite on the main thread.
retval = test_suite.Run();
} else {
// Create the test thread.
scoped_ptr<CefTestThread> thread;
thread.reset(new CefTestThread(&test_suite));
if (!thread->Start())
return 1;
// Run the test suite on the test thread.
thread->message_loop()->PostTask(FROM_HERE,
base::Bind(&CefTestThread::RunTests, base::Unretained(thread.get())));
// Run the CEF message loop.
CefRunMessageLoop();
// The test suite has completed.
retval = thread->retval();
// Terminate the test thread.
thread.reset();
}
// Shut down CEF.
CefShutdown();
#if defined(OS_MACOSX)
// Platform-specific cleanup.
extern void PlatformCleanup();
PlatformCleanup();
#endif
return retval;
}

View File

@ -0,0 +1,45 @@
// Copyright (c) 2011 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 "include/cef_app.h"
#import "include/cef_application_mac.h"
// Memory AutoRelease pool.
static NSAutoreleasePool* g_autopool = nil;
// Provide the CefAppProtocol implementation required by CEF.
@interface TestApplication : NSApplication<CefAppProtocol> {
@private
BOOL handlingSendEvent_;
}
@end
@implementation TestApplication
- (BOOL)isHandlingSendEvent {
return handlingSendEvent_;
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handlingSendEvent_ = handlingSendEvent;
}
- (void)sendEvent:(NSEvent*)event {
CefScopedSendingEvent sendingEventScoper;
[super sendEvent:event];
}
@end
void PlatformInit() {
// Initialize the AutoRelease pool.
g_autopool = [[NSAutoreleasePool alloc] init];
// Initialize the TestApplication instance.
[TestApplication sharedApplication];
}
void PlatformCleanup() {
// Release the AutoRelease pool.
[g_autopool release];
}

View File

@ -18,7 +18,8 @@ void NotifyEvent(base::WaitableEvent* event)
// TestHandler
TestHandler::TestHandler()
: browser_hwnd_(NULL), completion_event_(true, false)
: browser_hwnd_(NULL),
completion_event_(true, false)
{
}
@ -88,12 +89,9 @@ void TestHandler::ExecuteTest()
void TestHandler::DestroyTest()
{
Lock();
#if defined(OS_WIN)
AutoLock lock_scope(this);
if(browser_hwnd_ != NULL)
PostMessage(browser_hwnd_, WM_CLOSE, 0, 0);
#endif
Unlock();
browser_->CloseBrowser();
}
void TestHandler::CreateBrowser(const CefString& url)

View File

@ -3,48 +3,163 @@
// can be found in the LICENSE file.
#include "test_suite.h"
#include "include/cef_app.h"
#include "../cefclient/cefclient_switches.h"
#include "base/command_line.h"
#include "build/build_config.h"
#include "base/threading/platform_thread.h"
#include "base/logging.h"
#include "base/test/test_suite.h"
CefTestSuite::CefTestSuite(int argc, char** argv) : TestSuite(argc, argv) {
#if defined(OS_MACOSX)
#include "base/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/test/test_timeouts.h"
#endif
CommandLine* CefTestSuite::commandline_ = NULL;
CefTestSuite::CefTestSuite(int argc, char** argv)
: TestSuite(argc, argv) {
}
void CefTestSuite::Initialize() {
TestSuite::Initialize();
CefSettings settings;
settings.multi_threaded_message_loop = true;
std::string cache_path;
if (GetCachePath(cache_path)) {
// Set the cache_path value.
CefString(&settings.cache_path).FromASCII(cache_path.c_str());
// static
void CefTestSuite::InitCommandLine(int argc, const char* const* argv)
{
if (commandline_) {
// If this is intentional, Reset() must be called first. If we are using
// the shared build mode, we have to share a single object across multiple
// shared libraries.
return;
}
CefInitialize(settings, NULL);
commandline_ = new CommandLine(CommandLine::NO_PROGRAM);
#if defined(OS_WIN)
commandline_->ParseFromString(::GetCommandLineW());
#elif defined(OS_POSIX)
commandline_->InitFromArgv(argc, argv);
#endif
}
void CefTestSuite::Shutdown() {
// Delay a bit so that the system has a chance to finish destroying windows
// before CefShutdown() checks for memory leaks.
base::PlatformThread::Sleep(500);
// static
void CefTestSuite::GetSettings(CefSettings& settings) {
#if defined(OS_WIN)
settings.multi_threaded_message_loop =
commandline_->HasSwitch(cefclient::kMultiThreadedMessageLoop);
#endif
CefShutdown();
TestSuite::Shutdown();
CefString(&settings.cache_path) =
commandline_->GetSwitchValueASCII(cefclient::kCachePath);
CefString(&settings.user_agent) =
commandline_->GetSwitchValueASCII(cefclient::kUserAgent);
CefString(&settings.product_version) =
commandline_->GetSwitchValueASCII(cefclient::kProductVersion);
CefString(&settings.locale) =
commandline_->GetSwitchValueASCII(cefclient::kLocale);
CefString(&settings.log_file) =
commandline_->GetSwitchValueASCII(cefclient::kLogFile);
{
std::string str =
commandline_->GetSwitchValueASCII(cefclient::kLogSeverity);
bool invalid = false;
if (!str.empty()) {
if (str == cefclient::kLogSeverity_Verbose)
settings.log_severity = LOGSEVERITY_VERBOSE;
else if (str == cefclient::kLogSeverity_Info)
settings.log_severity = LOGSEVERITY_INFO;
else if (str == cefclient::kLogSeverity_Warning)
settings.log_severity = LOGSEVERITY_WARNING;
else if (str == cefclient::kLogSeverity_Error)
settings.log_severity = LOGSEVERITY_ERROR;
else if (str == cefclient::kLogSeverity_ErrorReport)
settings.log_severity = LOGSEVERITY_ERROR_REPORT;
else if (str == cefclient::kLogSeverity_Disable)
settings.log_severity = LOGSEVERITY_DISABLE;
else
invalid = true;
}
if (str.empty() || invalid) {
#ifdef NDEBUG
// Only log error messages and higher in release build.
settings.log_severity = LOGSEVERITY_ERROR;
#endif
}
}
{
std::string str =
commandline_->GetSwitchValueASCII(cefclient::kGraphicsImpl);
if (!str.empty()) {
#if defined(OS_WIN)
if (str == cefclient::kGraphicsImpl_Angle)
settings.graphics_implementation = ANGLE_IN_PROCESS;
else if (str == cefclient::kGraphicsImpl_AngleCmdBuffer)
settings.graphics_implementation = ANGLE_IN_PROCESS_COMMAND_BUFFER;
else
#endif
if (str == cefclient::kGraphicsImpl_Desktop)
settings.graphics_implementation = DESKTOP_IN_PROCESS;
else if (str == cefclient::kGraphicsImpl_DesktopCmdBuffer)
settings.graphics_implementation = DESKTOP_IN_PROCESS_COMMAND_BUFFER;
}
}
settings.local_storage_quota = atoi(commandline_->GetSwitchValueASCII(
cefclient::kLocalStorageQuota).c_str());
settings.session_storage_quota = atoi(commandline_->GetSwitchValueASCII(
cefclient::kSessionStorageQuota).c_str());
CefString(&settings.javascript_flags) =
commandline_->GetSwitchValueASCII(cefclient::kJavascriptFlags);
}
// static
bool CefTestSuite::GetCachePath(std::string& path) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
DCHECK(commandline_);
if (command_line->HasSwitch("cache_path")) {
if (commandline_->HasSwitch(cefclient::kCachePath)) {
// Set the cache_path value.
path = command_line->GetSwitchValueASCII("cache_path");
path = commandline_->GetSwitchValueASCII(cefclient::kCachePath);
return true;
}
return false;
}
#if defined(OS_MACOSX)
void CefTestSuite::Initialize() {
// The below code is copied from base/test/test_suite.cc to avoid calling
// RegisterMockCrApp() on Mac.
// Initialize logging.
FilePath exe;
PathService::Get(base::FILE_EXE, &exe);
FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
logging::InitLogging(
log_filename.value().c_str(),
logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
logging::LOCK_LOG_FILE,
logging::DELETE_OLD_LOG_FILE,
logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
// We want process and thread IDs because we may have multiple processes.
// Note: temporarily enabled timestamps in an effort to catch bug 6361.
logging::SetLogItems(true, true, true, true);
CHECK(base::EnableInProcessStackDumping());
// In some cases, we do not want to see standard error dialogs.
if (!base::debug::BeingDebugged() &&
!CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) {
SuppressErrorDialogs();
base::debug::SetSuppressDebugUI(true);
logging::SetLogAssertHandler(UnitTestAssertHandler);
}
icu_util::Initialize();
CatchMaybeTests();
ResetCommandLine();
TestTimeouts::Initialize();
}
#endif // defined(OS_MACOSX)

View File

@ -5,17 +5,31 @@
#ifndef _CEF_TEST_SUITE_H
#define _CEF_TEST_SUITE_H
#include "include/internal/cef_types_wrappers.h"
#include "base/test/test_suite.h"
class CommandLine;
class CefTestSuite : public TestSuite {
public:
CefTestSuite(int argc, char** argv);
// Initialize the current process CommandLine singleton. On Windows, ignores
// its arguments (we instead parse GetCommandLineW() directly) because we
// don't trust the CRT's parsing of the command line, but it still must be
// called to set up the command line.
static void InitCommandLine(int argc, const char* const* argv);
static void GetSettings(CefSettings& settings);
static bool GetCachePath(std::string& path);
protected:
#if defined(OS_MACOSX)
virtual void Initialize();
virtual void Shutdown();
#endif
// The singleton CommandLine representing the current process's command line.
static CommandLine* commandline_;
};
#endif // _CEF_TEST_SUITE_H

View File

@ -57,11 +57,13 @@ public:
ASSERT_EQ(date.year, 2010);
ASSERT_EQ(date.month, 5);
ASSERT_EQ(date.day_of_month, 3);
#if !defined(OS_MACOSX)
ASSERT_EQ(date.day_of_week, 1);
#endif
ASSERT_EQ(date.hour, 12);
ASSERT_EQ(date.minute, 30);
ASSERT_EQ(date.second, 10);
ASSERT_EQ(date.millisecond, 100);
ASSERT_NEAR(date.millisecond, 100, 1);
argct++;
ASSERT_TRUE(arguments[argct]->IsString());
@ -188,12 +190,14 @@ public:
CefTime date = value->GetDateValue();
ASSERT_EQ(date.year, 2010);
ASSERT_EQ(date.month, 5);
#if !defined(OS_MACOSX)
ASSERT_EQ(date.day_of_week, 1);
#endif
ASSERT_EQ(date.day_of_month, 3);
ASSERT_EQ(date.hour, 12);
ASSERT_EQ(date.minute, 30);
ASSERT_EQ(date.second, 10);
ASSERT_EQ(date.millisecond, 100);
ASSERT_NEAR(date.millisecond, 100, 1);
value = object->GetValue("arrayVal");
ASSERT_TRUE(value.get() != NULL);
@ -328,7 +332,18 @@ public:
ASSERT_TRUE(testObj->SetValue("stringVal",
CefV8Value::CreateString("the string"), V8_PROPERTY_ATTRIBUTE_NONE));
cef_time_t date = {2010, 5, 1, 3, 12, 30, 10, 100};
cef_time_t date = {
2010,
5,
#if !defined(OS_MACOSX)
1,
#endif
3,
12,
30,
10,
100
};
ASSERT_TRUE(testObj->SetValue("dateVal", CefV8Value::CreateDate(date),
V8_PROPERTY_ATTRIBUTE_NONE));