diff --git a/cef.gyp b/cef.gyp index cdb451dea..24cd3a90b 100644 --- a/cef.gyp +++ b/cef.gyp @@ -10,6 +10,7 @@ { 'target_name': 'cefclient', 'type': 'executable', + 'mac_bundle': 1, 'msvs_guid': '6617FED9-C5D4-4907-BF55-A90062A6683F', 'dependencies': [ '../third_party/npapi/npapi.gyp:npapi', @@ -32,17 +33,29 @@ 'tests/cefclient/download_handler.h', 'tests/cefclient/extension_test.cpp', 'tests/cefclient/extension_test.h', - 'tests/cefclient/plugin_test.cpp', - 'tests/cefclient/plugin_test.h', 'tests/cefclient/resource_util.h', 'tests/cefclient/scheme_test.cpp', 'tests/cefclient/scheme_test.h', 'tests/cefclient/string_util.cpp', 'tests/cefclient/string_util.h', - 'tests/cefclient/uiplugin_test.cpp', - 'tests/cefclient/uiplugin_test.h', 'tests/cefclient/util.h', ], + 'mac_bundle_resources': [ + 'tests/cefclient/mac/cefclient.icns', + 'tests/cefclient/mac/data/', + 'tests/cefclient/mac/English.lproj/InfoPlist.strings', + 'tests/cefclient/mac/English.lproj/MainMenu.xib', + 'tests/cefclient/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/cefclient/mac/Info.plist', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'tests/cefclient/mac/Info.plist', + }, 'conditions': [ ['OS=="win"', { 'msvs_settings': { @@ -67,6 +80,8 @@ 'tests/cefclient/cefclient_win.cpp', 'tests/cefclient/clientplugin.cpp', 'tests/cefclient/clientplugin.h', + 'tests/cefclient/plugin_test.cpp', + 'tests/cefclient/plugin_test.h', 'tests/cefclient/Resource.h', 'tests/cefclient/res/cefclient.ico', 'tests/cefclient/res/logo.jpg', @@ -77,6 +92,74 @@ 'tests/cefclient/string_util_win.cpp', 'tests/cefclient/uiplugin.cpp', 'tests/cefclient/uiplugin.h', + 'tests/cefclient/uiplugin_test.cpp', + 'tests/cefclient/uiplugin_test.h', + ], + }], + [ 'OS=="mac"', { + 'product_name': 'cefclient', + 'variables': { + 'repack_path': '../tools/data_pack/repack.py', + }, + 'actions': [ + { + # TODO(mark): Make this work with more languages than the + # hardcoded en-US. + 'action_name': 'repack_locale', + 'variables': { + 'pak_inputs': [ + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.pak', + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak', + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.pak', + ], + }, + 'inputs': [ + '<(repack_path)', + '<@(pak_inputs)', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/repack/cefclient.pak', + ], + 'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'], + 'process_outputs_as_mac_bundle_resources': 1, + }, + ], + 'copies': [ + # TODO(ajwong): This, and the parallel chromium stanza below + # really should find a way to share file paths with + # ffmpeg.gyp so they don't diverge. (BUG=23602) + { + 'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/MacOS/', + 'files': ['<(PRODUCT_DIR)/libffmpegsumo.dylib'], + }, + { + # TODO(tony): We should have cefclient.app load plugins from + # <(PRODUCT_DIR)/plugins so we don't have this extra copy of + # the plugin. + 'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/PlugIns/', + 'files': ['<(PRODUCT_DIR)/TestNetscapePlugIn.plugin/'], + }, + { + # Add the WebCore resources to the bundle. + 'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/', + 'files': ['../third_party/WebKit/WebCore/Resources/'], + }, + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + ], + }, + 'sources': [ + 'tests/cefclient/cefclient_mac.mm', + 'tests/cefclient/string_util_mac.h', + 'tests/cefclient/string_util_mac.mm', + ], + }], + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'sources': [ + 'tests/cefclient/cefclient_gtk.cpp', + 'tests/cefclient/string_util_gtk.cpp', ], }], ], @@ -461,6 +544,7 @@ 'libcef/browser_impl_win.cc', 'libcef/browser_webkit_glue_win.cc', 'libcef/browser_webview_delegate_win.cc', + 'libcef/cef_process_ui_thread_win.cc', 'libcef/printing/print_settings.cc', 'libcef/printing/print_settings.h', 'libcef/printing/win_printing_context.cc', @@ -478,6 +562,7 @@ 'libcef/browser_webview_delegate_mac.mm', 'libcef/browser_webview_mac.h', 'libcef/browser_webview_mac.mm', + 'libcef/cef_process_ui_thread_mac.mm', 'libcef/webview_host_mac.mm', 'libcef/webwidget_host_mac.mm', ], @@ -489,6 +574,7 @@ 'libcef/browser_impl_gtk.cc', 'libcef/browser_webkit_glue_gtk.cc', 'libcef/browser_webview_delegate_gtk.cc', + 'libcef/cef_process_ui_thread_gtk.cc', 'libcef/webview_host_gtk.cc', 'libcef/webwidget_host_gtk.cc', ], diff --git a/include/cef_mac.h b/include/cef_mac.h index db507742b..be7ef45d4 100644 --- a/include/cef_mac.h +++ b/include/cef_mac.h @@ -45,6 +45,9 @@ inline long CefAtomicDecrement(long volatile *pDest) return __sync_sub_and_fetch(pDest, 1); } +// Window handle. +#define CefWindowHandle cef_window_handle_t + // Critical section wrapper. class CefCriticalSection { @@ -100,12 +103,24 @@ public: void Init() { + m_View = NULL; + m_ParentView = NULL; m_windowName = NULL; m_x = 0; m_y = 0; m_nWidth = 0; m_nHeight = 0; } + + void SetAsChild(CefWindowHandle ParentView, int x, int y, int width, + int height) + { + m_ParentView = ParentView; + m_x = x; + m_y = y; + m_nWidth = width; + m_nHeight = height; + } CefWindowInfo& operator=(const CefWindowInfo& r) { @@ -113,6 +128,8 @@ public: } CefWindowInfo& operator=(const cef_window_info_t& r) { + m_View = r.m_View; + m_ParentView = r.m_ParentView; if(m_windowName) cef_string_free(m_windowName); if(r.m_windowName) @@ -166,8 +183,6 @@ public: } }; -// Window handle. -#define CefWindowHandle cef_window_handle_t #endif // defined(__APPLE__) #endif // _CEF_MAC_H diff --git a/include/cef_types_mac.h b/include/cef_types_mac.h index bae3209a4..8486d458e 100644 --- a/include/cef_types_mac.h +++ b/include/cef_types_mac.h @@ -51,11 +51,11 @@ typedef struct _cef_window_info_t int m_nWidth; int m_nHeight; - // NSWindow pointer for the parent window. - cef_window_handle_t m_ParentWindow; + // NSView pointer for the parent view. + cef_window_handle_t m_ParentView; - // NSWindow pointer for the new browser window. - cef_window_handle_t m_Window; + // NSView pointer for the new browser view. + cef_window_handle_t m_View; } cef_window_info_t; // Class representing print context information. diff --git a/include/cef_wrapper.h b/include/cef_wrapper.h index 04b64f1de..97dd14446 100644 --- a/include/cef_wrapper.h +++ b/include/cef_wrapper.h @@ -40,10 +40,6 @@ #include #include -#ifndef min -#define min(a,b) ((a)<(b)?(a):(b)) -#endif - // Thread safe class for representing XML data as a structured object. This // class should not be used with large XML documents because all data will be diff --git a/libcef/browser_impl.cc b/libcef/browser_impl.cc index bf4ce3181..26b5c9fe2 100644 --- a/libcef/browser_impl.cc +++ b/libcef/browser_impl.cc @@ -539,6 +539,25 @@ CefRefPtr CefBrowser::CreateBrowserSync(CefWindowInfo& windowInfo, return browser; } +void CefBrowserImpl::UIT_DestroyBrowser() +{ + if(handler_.get()) { + // Notify the handler that the window is about to be closed. + handler_->HandleBeforeWindowClose(this); + } + GetWebViewDelegate()->RevokeDragDrop(); + + // Clean up anything associated with the WebViewHost widget. + GetWebViewHost()->webwidget()->close(); + webviewhost_.reset(); + + // Remove the reference added in UIT_CreateBrowser(). + Release(); + + // Remove the browser from the list maintained by the context. + _Context->RemoveBrowser(this); +} + void CefBrowserImpl::UIT_LoadURL(CefFrame* frame, const std::wstring& url) { diff --git a/libcef/browser_impl.h b/libcef/browser_impl.h index 78b5b8005..35be6e7be 100644 --- a/libcef/browser_impl.h +++ b/libcef/browser_impl.h @@ -160,6 +160,7 @@ public: } void UIT_CreateBrowser(const std::wstring& url); + void UIT_DestroyBrowser(); void UIT_LoadURL(CefFrame* frame, const std::wstring& url); diff --git a/libcef/browser_impl_mac.mm b/libcef/browser_impl_mac.mm index 5bec43ac7..5b8f20e67 100644 --- a/libcef/browser_impl_mac.mm +++ b/libcef/browser_impl_mac.mm @@ -5,6 +5,7 @@ #include "cef_context.h" #include "browser_impl.h" +#include "browser_webview_mac.h" #import @@ -20,36 +21,38 @@ using WebKit::WebSize; CefWindowHandle CefBrowserImpl::GetWindowHandle() { Lock(); - CefWindowHandle handle = window_info_.m_Window; + CefWindowHandle handle = window_info_.m_View; Unlock(); return handle; } gfx::NativeWindow CefBrowserImpl::GetMainWndHandle() const { - return (NSWindow*)window_info_.m_Window; + return (NSWindow*)window_info_.m_View; } void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url) { REQUIRE_UIT(); - // Create the new browser window - // TODO(port): Add implementation. - - // Add a reference that will be released on WM_DESTROY. + // Add a reference that will be released in UIT_DestroyBrowser(). AddRef(); // Add the new browser to the list maintained by the context _Context->AddBrowser(this); + + NSView* parentView = (NSView*)window_info_.m_ParentView; + gfx::Rect contentRect(window_info_.m_x, window_info_.m_y, + window_info_.m_nWidth, window_info_.m_nHeight); // Create the webview host object webviewhost_.reset( - WebViewHost::Create([GetMainWndHandle() contentView], delegate_.get(), - NULL, *_Context->web_preferences())); + WebViewHost::Create(parentView, contentRect, delegate_.get(), + NULL, *_Context->web_preferences())); delegate_->RegisterDragDrop(); - - // Size the web view window to the browser window - // TODO(port): Add implementation. + + BrowserWebView* browserView = (BrowserWebView*)webviewhost_->view_handle(); + browserView.browser = this; + window_info_.m_View = (void*)browserView; if(handler_.get()) { // Notify the handler that we're done creating the new window @@ -68,8 +71,13 @@ void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable) REQUIRE_UIT(); if (!host) return; + + NSView* view = host->view_handle(); + if (!view) + return; - // TODO(port): Add implementation. + if (enable) + [[view window] makeFirstResponder:view]; } WebKit::WebWidget* CefBrowserImpl::UIT_CreatePopupWidget() diff --git a/libcef/browser_impl_win.cc b/libcef/browser_impl_win.cc index fed4bfad6..f346b6411 100644 --- a/libcef/browser_impl_win.cc +++ b/libcef/browser_impl_win.cc @@ -46,26 +46,12 @@ LRESULT CALLBACK CefBrowserImpl::WndProc(HWND hwnd, UINT message, break; case WM_DESTROY: - if (browser) - { - CefRefPtr handler = browser->GetHandler(); - if(handler.get()) { - // Notify the handler that the window is about to be closed - handler->HandleBeforeWindowClose(browser); - } - browser->GetWebViewDelegate()->RevokeDragDrop(); - - // Clean up anything associated with the WebViewHost widget. - browser->GetWebViewHost()->webwidget()->close(); - browser->webviewhost_.reset(); - + if (browser) { // Clear the user data pointer. win_util::SetWindowUserData(hwnd, NULL); - // Remove the reference added in UIT_CreateBrowser(). - browser->Release(); - // Remove the browser from the list maintained by the context - _Context->RemoveBrowser(browser); + // Destroy the browser. + browser->UIT_DestroyBrowser(); } return 0; @@ -123,7 +109,8 @@ void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url) // Set window user data to this object for future reference from the window // procedure win_util::SetWindowUserData(window_info_.m_hWnd, this); - // Add a reference that will be released on WM_DESTROY. + + // Add a reference that will be released in UIT_DestroyBrowser(). AddRef(); // Add the new browser to the list maintained by the context @@ -131,8 +118,8 @@ void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url) // Create the webview host object webviewhost_.reset( - WebViewHost::Create(window_info_.m_hWnd, delegate_.get(), NULL, - *_Context->web_preferences())); + WebViewHost::Create(window_info_.m_hWnd, gfx::Rect(), delegate_.get(), + NULL, *_Context->web_preferences())); delegate_->RegisterDragDrop(); // Size the web view window to the browser window diff --git a/libcef/browser_webkit_glue.h b/libcef/browser_webkit_glue.h index b512546bb..db833a227 100644 --- a/libcef/browser_webkit_glue.h +++ b/libcef/browser_webkit_glue.h @@ -26,6 +26,10 @@ void CaptureWebViewBitmap(HWND mainWnd, WebKit::WebView* webview, // Save a bitmap image to file, providing optional alternative data in |lpBits| BOOL SaveBitmapToFile(HBITMAP hBmp, HDC hDC, LPCTSTR file, LPBYTE lpBits); #endif + +#if defined(OS_MACOSX) +void InitializeDataPak(); +#endif // Text encoding objects must be initialized on the main thread. void InitializeTextEncoding(); diff --git a/libcef/browser_webkit_glue_mac.mm b/libcef/browser_webkit_glue_mac.mm index a480a19e0..cfbfcea73 100644 --- a/libcef/browser_webkit_glue_mac.mm +++ b/libcef/browser_webkit_glue_mac.mm @@ -24,6 +24,17 @@ namespace webkit_glue { // Data pack resource. This is a pointer to the mmapped resources file. static base::DataPack* g_resource_data_pack = NULL; +void InitializeDataPak() { + // mmap the data pack which holds strings used by WebCore. + // TODO(port): Allow the embedder to customize the pak name. + g_resource_data_pack = new base::DataPack; + NSString *resource_path = + [mac_util::MainAppBundle() pathForResource:@"cefclient" ofType:@"pak"]; + FilePath resources_pak_path([resource_path fileSystemRepresentation]); + if (!g_resource_data_pack->Load(resources_pak_path)) + LOG(FATAL) << "failed to load cefclient.pak"; +} + // Helper method for getting the path to the CEF resources directory. FilePath GetResourcesFilePath() { FilePath path; @@ -33,10 +44,13 @@ FilePath GetResourcesFilePath() { path = path.Append(FilePath::kParentDirectory); return path.AppendASCII("Resources"); } else { + // TODO(port): Allow the embedder to customize the resource path. PathService::Get(base::DIR_SOURCE_ROOT, &path); path = path.AppendASCII("src"); path = path.AppendASCII("cef"); - return path.AppendASCII("resources"); + path = path.AppendASCII("tests"); + path = path.AppendASCII("cefclient"); + return path.AppendASCII("res"); } } diff --git a/libcef/browser_webview_delegate_mac.mm b/libcef/browser_webview_delegate_mac.mm index 67dc5f40b..dabe080fc 100644 --- a/libcef/browser_webview_delegate_mac.mm +++ b/libcef/browser_webview_delegate_mac.mm @@ -198,13 +198,14 @@ void BrowserWebViewDelegate::DidMovePlugin( void BrowserWebViewDelegate::ShowJavaScriptAlert( WebKit::WebFrame* webframe, const std::wstring& message) { NSString *text = - [NSString stringWithUTF8String:WideToUTF8(message).c_str()]; + [NSString stringWithUTF8String:WideToUTF8(message).c_str()]; NSAlert *alert = [NSAlert alertWithMessageText:@"JavaScript Alert" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:text]; [alert runModal]; + [text release]; } bool BrowserWebViewDelegate::ShowJavaScriptConfirm( diff --git a/libcef/browser_webview_mac.h b/libcef/browser_webview_mac.h index cfb9e0689..b61012ab5 100644 --- a/libcef/browser_webview_mac.h +++ b/libcef/browser_webview_mac.h @@ -15,12 +15,6 @@ class CefBrowserImpl; NSTrackingArea *trackingArea_; } -- (IBAction)goBack:(id)sender; -- (IBAction)goForward:(id)sender; -- (IBAction)reload:(id)sender; -- (IBAction)stopLoading:(id)sender; -- (IBAction)takeURLStringValueFrom:(NSTextField *)sender; - - (void)mouseDown:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)otherMouseDown:(NSEvent *)theEvent; @@ -38,7 +32,6 @@ class CefBrowserImpl; - (void)keyUp:(NSEvent *)theEvent; - (BOOL)isOpaque; - (void)setFrame:(NSRect)frameRect; -- (void)setIsActive:(BOOL)active; @property (nonatomic, assign) CefBrowserImpl *browser; diff --git a/libcef/browser_webview_mac.mm b/libcef/browser_webview_mac.mm index d3393f2f9..518d0f724 100644 --- a/libcef/browser_webview_mac.mm +++ b/libcef/browser_webview_mac.mm @@ -7,6 +7,7 @@ #import #include "browser_impl.h" +#include "cef_context.h" #include "webwidget_host.h" #include "base/scoped_ptr.h" @@ -35,9 +36,11 @@ } - (void) dealloc { + browser_->UIT_DestroyBrowser(); + [self removeTrackingArea:trackingArea_]; [trackingArea_ release]; - + [super dealloc]; } @@ -61,37 +64,6 @@ } } -- (IBAction)goBack:(id)sender { - if (browser_) - browser_->UIT_GoBackOrForward(-1); -} - -- (IBAction)goForward:(id)sender { - if (browser_) - browser_->UIT_GoBackOrForward(1); -} - -- (IBAction)reload:(id)sender { - if (browser_) - browser_->UIT_Reload(false); -} - -- (IBAction)stopLoading:(id)sender { - if (browser_ && browser_->GetWebView()) - browser_->GetWebView()->mainFrame()->stopLoading(); -} - -- (IBAction)takeURLStringValueFrom:(NSTextField *)sender { - NSString *url = [sender stringValue]; - - // if it doesn't already have a prefix, add http. If we can't parse it, - // just don't bother rather than making things worse. - NSURL* tempUrl = [NSURL URLWithString:url]; - if (tempUrl && ![tempUrl scheme]) - url = [@"http://" stringByAppendingString:url]; - browser_->LoadURL(browser_->GetMainFrame(), UTF8ToWide([url UTF8String])); -} - - (void)mouseDown:(NSEvent *)theEvent { if (browser_ && browser_->GetWebView()) browser_->GetWebViewHost()->MouseEvent(theEvent); @@ -197,11 +169,6 @@ return NO; } -- (void)setIsActive:(BOOL)active { - if (browser_ && browser_->GetWebView()) - browser_->GetWebViewHost()->SetIsActive(active ? true : false); -} - - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; if (browser_ && browser_->GetWebView()) diff --git a/libcef/cef_process_ui_thread.cc b/libcef/cef_process_ui_thread.cc index 6e33961ee..8e1c56ac9 100644 --- a/libcef/cef_process_ui_thread.cc +++ b/libcef/cef_process_ui_thread.cc @@ -4,9 +4,6 @@ // found in the LICENSE file. #include "cef_process_ui_thread.h" -#include "browser_impl.h" -#include "browser_resource_loader_bridge.h" -#include "browser_request_context.h" #include "browser_webkit_glue.h" #include "browser_webkit_init.h" #include "cef_context.h" @@ -66,38 +63,7 @@ CefProcessUIThread::~CefProcessUIThread() { } void CefProcessUIThread::Init() { -#if defined(OS_WIN) - HRESULT res; - - // Initialize common controls - res = CoInitialize(NULL); - DCHECK(SUCCEEDED(res)); - INITCOMMONCONTROLSEX InitCtrlEx; - InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); - InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; - InitCommonControlsEx(&InitCtrlEx); - - // Start COM stuff - res = OleInitialize(NULL); - DCHECK(SUCCEEDED(res)); - - // Register the window class - WNDCLASSEX wcex = { - /* cbSize = */ sizeof(WNDCLASSEX), - /* style = */ CS_HREDRAW | CS_VREDRAW, - /* lpfnWndProc = */ CefBrowserImpl::WndProc, - /* cbClsExtra = */ 0, - /* cbWndExtra = */ 0, - /* hInstance = */ ::GetModuleHandle(NULL), - /* hIcon = */ NULL, - /* hCursor = */ LoadCursor(NULL, IDC_ARROW), - /* hbrBackground = */ 0, - /* lpszMenuName = */ NULL, - /* lpszClassName = */ CefBrowserImpl::GetWndClass(), - /* hIconSm = */ NULL, - }; - RegisterClassEx(&wcex); -#endif + PlatformInit(); #ifndef _DEBUG // Only log error messages and above in release build. @@ -167,12 +133,5 @@ void CefProcessUIThread::CleanUp() { delete webkit_init_; webkit_init_ = NULL; -#if defined(OS_WIN) - // Uninitialize COM stuff - OleUninitialize(); - - // Closes the COM library on the current thread. CoInitialize must - // be balanced by a corresponding call to CoUninitialize. - CoUninitialize(); -#endif + PlatformCleanUp(); } diff --git a/libcef/cef_process_ui_thread.h b/libcef/cef_process_ui_thread.h index cc26ecce3..9703267af 100644 --- a/libcef/cef_process_ui_thread.h +++ b/libcef/cef_process_ui_thread.h @@ -33,6 +33,9 @@ class CefProcessUIThread : public CefThread { virtual void CleanUp(); private: + void PlatformInit(); + void PlatformCleanUp(); + base::StatsTable* statstable_; // WebKit implementation class. diff --git a/libcef/cef_process_ui_thread_mac.mm b/libcef/cef_process_ui_thread_mac.mm new file mode 100644 index 000000000..44725ef83 --- /dev/null +++ b/libcef/cef_process_ui_thread_mac.mm @@ -0,0 +1,51 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2010 The Chromium 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.h" +#include "cef_process_ui_thread.h" +#include "browser_webkit_glue.h" +#include "base/chrome_application_mac.h" +#include "third_party/WebKit/WebKit/mac/WebCoreSupport/WebSystemInterface.h" + +namespace { + +// Memory autorelease pool. +NSAutoreleasePool* g_autopool; + +void RunLoopObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, + void* info) +{ + CefDoMessageLoopWork(); +} + +} // namespace + +void CefProcessUIThread::PlatformInit() { + // Initialize the CrApplication instance. + [CrApplication sharedApplication]; + g_autopool = [[NSAutoreleasePool alloc] init]; + + InitWebCoreSystemInterface(); + + // Register the run loop observer. + CFRunLoopObserverRef observer = + CFRunLoopObserverCreate(NULL, + kCFRunLoopBeforeTimers | kCFRunLoopBeforeWaiting, + YES, /* repeat */ + 0, + &RunLoopObserver, + NULL); + if (observer) { + CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, + kCFRunLoopCommonModes); + } + + webkit_glue::InitializeDataPak(); +} + +void CefProcessUIThread::PlatformCleanUp() { + [g_autopool release]; +} + diff --git a/libcef/cef_process_ui_thread_win.cc b/libcef/cef_process_ui_thread_win.cc new file mode 100644 index 000000000..22b7c1ef8 --- /dev/null +++ b/libcef/cef_process_ui_thread_win.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2010 The Chromium 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 "cef_process_ui_thread.h" +#include "browser_impl.h" +#include +#include + +void CefProcessUIThread::PlatformInit() { + HRESULT res; + + // Initialize common controls + res = CoInitialize(NULL); + DCHECK(SUCCEEDED(res)); + INITCOMMONCONTROLSEX InitCtrlEx; + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + + // Start COM stuff + res = OleInitialize(NULL); + DCHECK(SUCCEEDED(res)); + + // Register the window class + WNDCLASSEX wcex = { + /* cbSize = */ sizeof(WNDCLASSEX), + /* style = */ CS_HREDRAW | CS_VREDRAW, + /* lpfnWndProc = */ CefBrowserImpl::WndProc, + /* cbClsExtra = */ 0, + /* cbWndExtra = */ 0, + /* hInstance = */ ::GetModuleHandle(NULL), + /* hIcon = */ NULL, + /* hCursor = */ LoadCursor(NULL, IDC_ARROW), + /* hbrBackground = */ 0, + /* lpszMenuName = */ NULL, + /* lpszClassName = */ CefBrowserImpl::GetWndClass(), + /* hIconSm = */ NULL, + }; + RegisterClassEx(&wcex); +} + +void CefProcessUIThread::PlatformCleanUp() { + // Uninitialize COM stuff + OleUninitialize(); + + // Closes the COM library on the current thread. CoInitialize must + // be balanced by a corresponding call to CoUninitialize. + CoUninitialize(); +} + diff --git a/libcef/v8_impl.cc b/libcef/v8_impl.cc index 621f4d2d1..1d39caa02 100644 --- a/libcef/v8_impl.cc +++ b/libcef/v8_impl.cc @@ -58,16 +58,19 @@ static void TrackDestructor(v8::Persistent object, // Convert a wide string to a V8 string. static v8::Handle GetV8String(const std::wstring& str) { - return v8::String::New( - reinterpret_cast(str.c_str()), str.length()); + std::string tmpStr = WideToUTF8(str); + return v8::String::New(tmpStr.c_str(), tmpStr.length()); } // Convert a V8 string to a wide string. static std::wstring GetWString(v8::Handle str) { - uint16_t* buf = new uint16_t[str->Length()+1]; - str->Write(buf); - std::wstring value = reinterpret_cast(buf); + // Allocate enough space for a worst-case conversion. + size_t len = str->Length()*4; + char* buf = new char[len]; + int newlen = str->WriteUtf8(buf, len); + std::wstring value; + UTF8ToWide(buf, newlen, &value); delete [] buf; return value; } diff --git a/libcef/webview_host.h b/libcef/webview_host.h index 142fc4337..47b2aaa7c 100644 --- a/libcef/webview_host.h +++ b/libcef/webview_host.h @@ -6,7 +6,6 @@ #define _WEBVIEW_HOST_H #include "base/basictypes.h" -#include "gfx/rect.h" #include "gfx/native_widget_types.h" #include "webwidget_host.h" @@ -29,6 +28,7 @@ class WebViewHost : public WebWidgetHost { // The newly created window should be resized after it is created, using the // MoveWindow (or equivalent) function. static WebViewHost* Create(gfx::NativeView parent_view, + const gfx::Rect& rect, BrowserWebViewDelegate* delegate, WebKit::WebDevToolsAgentClient* devtools_client, const WebPreferences& prefs); diff --git a/libcef/webview_host_mac.mm b/libcef/webview_host_mac.mm index 5ebd64ff9..2711bbe6c 100644 --- a/libcef/webview_host_mac.mm +++ b/libcef/webview_host_mac.mm @@ -21,17 +21,13 @@ using WebKit::WebView; // static WebViewHost* WebViewHost::Create(NSView* parent_view, + const gfx::Rect& rect, BrowserWebViewDelegate* delegate, WebDevToolsAgentClient* dev_tools_client, const WebPreferences& prefs) { WebViewHost* host = new WebViewHost(); - NSRect content_rect = [parent_view frame]; - // bump down the top of the view so that it doesn't overlap the buttons - // and URL field. 32 is an ad hoc constant. - // TODO(awalker): replace explicit view layout with a little nib file - // and use that for view geometry. - content_rect.size.height -= 32; + NSRect content_rect = {{rect.x(), rect.y()}, {rect.width(), rect.height()}}; host->view_ = [[BrowserWebView alloc] initWithFrame:content_rect]; // make the height and width track the window size. [host->view_ setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; diff --git a/libcef/webview_host_win.cc b/libcef/webview_host_win.cc index 94b45d26f..691fb7b19 100644 --- a/libcef/webview_host_win.cc +++ b/libcef/webview_host_win.cc @@ -17,6 +17,7 @@ static const wchar_t kWindowClassName[] = L"WebViewHost"; /*static*/ WebViewHost* WebViewHost::Create(HWND parent_view, + const gfx::Rect&, BrowserWebViewDelegate* delegate, WebDevToolsAgentClient* dev_tools_client, const WebPreferences& prefs) { diff --git a/libcef/webwidget_host.h b/libcef/webwidget_host.h index 989eb5f3b..dea8710cb 100644 --- a/libcef/webwidget_host.h +++ b/libcef/webwidget_host.h @@ -14,6 +14,7 @@ #include namespace gfx { +class Rect; class Size; } diff --git a/libcef/webwidget_host_mac.mm b/libcef/webwidget_host_mac.mm index d9b81df1a..07b69c0ae 100644 --- a/libcef/webwidget_host_mac.mm +++ b/libcef/webwidget_host_mac.mm @@ -35,13 +35,9 @@ WebWidgetHost* WebWidgetHost::Create(NSView* parent_view, WebWidgetHost* host = new WebWidgetHost(); NSRect content_rect = [parent_view frame]; - content_rect.origin.y += 64; - content_rect.size.height -= 64; host->view_ = [[NSView alloc] initWithFrame:content_rect]; [parent_view addSubview:host->view_]; - // win_util::SetWindowUserData(host->hwnd_, host); - host->webwidget_ = WebPopupMenu::create(client); host->webwidget_->resize(WebSize(content_rect.size.width, content_rect.size.height)); @@ -137,9 +133,6 @@ void WebWidgetHost::ScheduleComposite() { [view_ setNeedsDisplayInRect:r]; } -// void WebWidgetHost::SetCursor(HCURSOR cursor) { -// } - void WebWidgetHost::DiscardBackingStore() { canvas_.reset(); } @@ -153,9 +146,6 @@ WebWidgetHost::WebWidgetHost() } WebWidgetHost::~WebWidgetHost() { - // win_util::SetWindowUserData(hwnd_, 0); - - webwidget_->close(); } void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) { @@ -225,7 +215,7 @@ void WebWidgetHost::Paint() { } void WebWidgetHost::SetTooltipText(const std::wstring& tooltip_text) { - NOTIMPLEMENTED(); + // TODO(port): Implement this method. } WebScreenInfo WebWidgetHost::GetScreenInfo() { diff --git a/libcef/zip_reader_impl.h b/libcef/zip_reader_impl.h index 0ed9b723c..a44d52dd8 100644 --- a/libcef/zip_reader_impl.h +++ b/libcef/zip_reader_impl.h @@ -40,13 +40,13 @@ public: bool VerifyContext(); protected: + PlatformThreadId supported_thread_id_; unzFile reader_; bool has_fileopen_; bool has_fileinfo_; std::wstring filename_; long filesize_; time_t filemodified_; - PlatformThreadId supported_thread_id_; }; #endif // _ZIP_READER_IMPL_H diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 1219a1163..bda41fe7a 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -164,4 +164,4 @@ CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId, return 0; return CefPostDelayedTask(threadId, CefTaskCToCpp::Wrap(task), delay_ms); -} \ No newline at end of file +} diff --git a/libcef_dll/wrapper/cef_byte_read_handler.cc b/libcef_dll/wrapper/cef_byte_read_handler.cc index 687dcbc6f..c1b3f2b63 100644 --- a/libcef_dll/wrapper/cef_byte_read_handler.cc +++ b/libcef_dll/wrapper/cef_byte_read_handler.cc @@ -15,7 +15,7 @@ size_t CefByteReadHandler::Read(void* ptr, size_t size, size_t n) { Lock(); size_t s = (size_ - offset_) / size; - size_t ret = min(n, s); + size_t ret = std::min(n, s); memcpy(ptr, bytes_ + offset_, ret * size); offset_ += ret * size; Unlock(); diff --git a/libcef_dll/wrapper/cef_xml_object.cc b/libcef_dll/wrapper/cef_xml_object.cc index 31b9fdbbf..3564a2935 100644 --- a/libcef_dll/wrapper/cef_xml_object.cc +++ b/libcef_dll/wrapper/cef_xml_object.cc @@ -104,7 +104,7 @@ public: cur_object->GetName() != reader->GetQualifiedName()) { // Open tag without close tag or close tag without open tag should // never occur (the parser catches this error). - DCHECK(FALSE); + DCHECK(false); std::wstringstream ss; ss << L"Mismatched end tag for " << cur_object->GetName() << L", line " << reader->GetLineNumber(); diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index de75b327a..f0f4f4666 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -175,14 +175,24 @@ CefHandler::RetVal ClientHandler::HandleConsoleMessage( bool first_message = m_LogFile.empty(); if(first_message) { std::wstringstream ss; - ss << AppGetWorkingDirectory() << L"\\console.log"; + ss << AppGetWorkingDirectory(); +#ifdef _WIN32 + ss << L"\\"; +#else + ss << L"/"; +#endif + ss << L"console.log"; m_LogFile = ss.str(); } std::wstring logFile = m_LogFile; Unlock(); FILE* file = NULL; +#ifdef _WIN32 _wfopen_s(&file, logFile.c_str(), L"a, ccs=UTF-8"); +#else + file = fopen(WStringToString(logFile).c_str(), "a"); +#endif if(file) { std::wstringstream ss; diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm new file mode 100644 index 000000000..2c978d02b --- /dev/null +++ b/tests/cefclient/cefclient_mac.mm @@ -0,0 +1,444 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2010 The Chromium 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.h" +#include "include/cef_wrapper.h" +#include "cefclient.h" +#include "binding_test.h" +#include "extension_test.h" +#include "scheme_test.h" +#include "string_util.h" +#include "string_util_mac.h" +#import +#include + +// The global ClientHandler reference. +extern CefRefPtr g_handler; + +char szWorkingDir[512]; // The current working directory + +// Sizes for URL bar layout +#define BUTTON_HEIGHT 22 +#define BUTTON_WIDTH 72 +#define BUTTON_MARGIN 8 +#define URLBAR_HEIGHT 32 + +// Content area size for newly created windows. +const int kWindowWidth = 800; +const int kWindowHeight = 600; + + +// Receives notifications from controls and the browser window. Will delete +// itself when done. +@interface ClientWindowDelegate : NSObject +- (IBAction)goBack:(id)sender; +- (IBAction)goForward:(id)sender; +- (IBAction)reload:(id)sender; +- (IBAction)stopLoading:(id)sender; +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender; +- (void)alert:(NSString*)title withMessage:(NSString*)message; +- (void)notifyConsoleMessage:(id)object; +- (void)notifyDownloadComplete:(id)object; +- (void)notifyDownloadError:(id)object; +@end + +@implementation ClientWindowDelegate + +- (IBAction)goBack:(id)sender { + if (g_handler.get() && g_handler->GetBrowserHwnd()) + g_handler->GetBrowser()->GoBack(); +} + +- (IBAction)goForward:(id)sender { + if (g_handler.get() && g_handler->GetBrowserHwnd()) + g_handler->GetBrowser()->GoForward(); +} + +- (IBAction)reload:(id)sender { + if (g_handler.get() && g_handler->GetBrowserHwnd()) + g_handler->GetBrowser()->Reload(); +} + +- (IBAction)stopLoading:(id)sender { + if (g_handler.get() && g_handler->GetBrowserHwnd()) + g_handler->GetBrowser()->StopLoad(); +} + +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender { + if (!g_handler.get() || !g_handler->GetBrowserHwnd()) + return; + + NSString *url = [sender stringValue]; + + // if it doesn't already have a prefix, add http. If we can't parse it, + // just don't bother rather than making things worse. + NSURL* tempUrl = [NSURL URLWithString:url]; + if (tempUrl && ![tempUrl scheme]) + url = [@"http://" stringByAppendingString:url]; + + std::wstring urlStr = NSStringToWString(url); + g_handler->GetBrowser()->GetMainFrame()->LoadURL(urlStr); +} + +- (void)alert:(NSString*)title withMessage:(NSString*)message { + NSAlert *alert = [NSAlert alertWithMessageText:title + defaultButton:@"OK" + alternateButton:nil + otherButton:nil + informativeTextWithFormat:message]; + [alert runModal]; +} + +- (void)notifyConsoleMessage:(id)object { + std::wstringstream ss; + ss << L"Console messages will be written to " << g_handler->GetLogFile(); + NSString* str = WStringToNSString(ss.str()); + [self alert:@"Console Messages" withMessage:str]; + [str release]; +} + +- (void)notifyDownloadComplete:(id)object { + std::wstringstream ss; + ss << L"File \"" << g_handler->GetLastDownloadFile() << + L"\" downloaded successfully."; + NSString* str = WStringToNSString(ss.str()); + [self alert:@"File Download" withMessage:str]; + [str release]; +} + +- (void)notifyDownloadError:(id)object { + std::wstringstream ss; + ss << L"File \"" << g_handler->GetLastDownloadFile() << + L"\" failed to download."; + NSString* str = WStringToNSString(ss.str()); + [self alert:@"File Download" withMessage:str]; + [str release]; +} + +- (void)windowDidBecomeKey:(NSNotification*)notification { + if(g_handler.get() && g_handler->GetBrowserHwnd()) { + // Give focus to the browser window. + g_handler->GetBrowser()->SetFocus(true); + } +} + +// Called when the window is about to close. Perform the self-destruction +// sequence by getting rid of the window. By returning YES, we allow the window +// to be removed from the screen. +- (BOOL)windowShouldClose:(id)window { + // Try to make the window go away. + [window autorelease]; + + // Clean ourselves up after clearing the stack of anything that might have the + // window on it. + [self performSelectorOnMainThread:@selector(cleanup:) + withObject:window + waitUntilDone:NO]; + + return YES; +} + +// Deletes itself. +- (void)cleanup:(id)window { + [self release]; +} + +@end + + +NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { + NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; + [button setTitle:title]; + [button setBezelStyle:NSSmallSquareBezelStyle]; + [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; + [parent addSubview:button]; + rect->origin.x += BUTTON_WIDTH; + return button; +} + +// Receives notifications from the application. Will delete itself when done. +@interface ClientAppDelegate : NSObject +- (void)createApp:(id)object; +- (IBAction)testGetSource:(id)sender; +- (IBAction)testGetText:(id)sender; +- (IBAction)testJSBinding:(id)sender; +- (IBAction)testJSExtension:(id)sender; +- (IBAction)testJSExecute:(id)sender; +- (IBAction)testRequest:(id)sender; +- (IBAction)testSchemeHandler:(id)sender; +@end + +@implementation ClientAppDelegate + +// Create the application on the UI thread. +- (void)createApp:(id)object { + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; + + // Set the delegate for application events. + [NSApp setDelegate:self]; + + // Add the Tests menu. + NSMenu* menubar = [NSApp mainMenu]; + NSMenuItem *testItem = [[[NSMenuItem alloc] initWithTitle:@"Tests" + action:nil + keyEquivalent:@""] autorelease]; + NSMenu *testMenu = [[[NSMenu alloc] initWithTitle:@"Tests"] autorelease]; + [testMenu addItemWithTitle:@"Get Source" + action:@selector(testGetSource:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Get Text" + action:@selector(testGetText:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"JavaScript Binding Handler" + action:@selector(testJSBinding:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"JavaScript Extension Handler" + action:@selector(testJSExtension:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"JavaScript Execute" + action:@selector(testJSExecute:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Request" + action:@selector(testRequest:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Scheme Handler" + action:@selector(testSchemeHandler:) + keyEquivalent:@""]; + [testItem setSubmenu:testMenu]; + [menubar addItem:testItem]; + + // Create the delegate for control and browser window events. + NSObject* delegate = [[ClientWindowDelegate alloc] init]; + + // Create the main application window. + NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; + NSRect window_rect = { {0, screen_rect.size.height - kWindowHeight}, + {kWindowWidth, kWindowHeight} }; + NSWindow* mainWnd = [[NSWindow alloc] + initWithContentRect:window_rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask ) + backing:NSBackingStoreBuffered + defer:NO]; + [mainWnd setTitle:@"cefclient"]; + [mainWnd setDelegate:delegate]; + + // Rely on the window delegate to clean us up rather than immediately + // releasing when the window gets closed. We use the delegate to do + // everything from the autorelease pool so the window isn't on the stack + // during cleanup (ie, a window close from javascript). + [mainWnd setReleasedWhenClosed:NO]; + + // Create the buttons. + NSRect button_rect = [[mainWnd contentView] bounds]; + button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; + button_rect.size.height = BUTTON_HEIGHT; + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = BUTTON_WIDTH; + + NSView* content = [mainWnd contentView]; + + NSButton* button = MakeButton(&button_rect, @"Back", content); + [button setTarget:delegate]; + [button setAction:@selector(goBack:)]; + + button = MakeButton(&button_rect, @"Forward", content); + [button setTarget:delegate]; + [button setAction:@selector(goForward:)]; + + button = MakeButton(&button_rect, @"Reload", content); + [button setTarget:delegate]; + [button setAction:@selector(reload:)]; + + button = MakeButton(&button_rect, @"Stop", content); + [button setTarget:delegate]; + [button setAction:@selector(stopLoading:)]; + + // Create the URL text field. + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = [[mainWnd contentView] bounds].size.width - + button_rect.origin.x - BUTTON_MARGIN; + NSTextField* editWnd = [[NSTextField alloc] initWithFrame:button_rect]; + [[mainWnd contentView] addSubview:editWnd]; + [editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; + [editWnd setTarget:delegate]; + [editWnd setAction:@selector(takeURLStringValueFrom:)]; + [[editWnd cell] setWraps:NO]; + [[editWnd cell] setScrollable:YES]; + + // Create the handler. + g_handler = new ClientHandler(); + g_handler->SetMainHwnd(mainWnd); + g_handler->SetEditHwnd(editWnd); + + // Create the browser view. + CefWindowInfo window_info; + window_info.SetAsChild((void*)[mainWnd contentView], 0, 0, + kWindowWidth, kWindowHeight); + CefBrowser::CreateBrowser(window_info, false, g_handler.get(), + L"http://www.google.com"); + + // Show the window. + [mainWnd makeKeyAndOrderFront: nil]; + + // Size the window. + NSRect r = [mainWnd contentRectForFrameRect:[mainWnd frame]]; + r.size.width = kWindowWidth; + r.size.height = kWindowHeight + URLBAR_HEIGHT; + [mainWnd setFrame:[mainWnd frameRectForContentRect:r] display:YES]; +} + +- (IBAction)testGetSource:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunGetSourceTest(g_handler->GetBrowser()->GetMainFrame()); +} + +- (IBAction)testGetText:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunGetTextTest(g_handler->GetBrowser()->GetMainFrame()); +} + +- (IBAction)testJSBinding:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunBindingTest(g_handler->GetBrowser()); +} + +- (IBAction)testJSExtension:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunExtensionTest(g_handler->GetBrowser()); +} + +- (IBAction)testJSExecute:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunJavaScriptExecuteTest(g_handler->GetBrowser()); +} + +- (IBAction)testRequest:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunRequestTest(g_handler->GetBrowser()); +} + +- (IBAction)testSchemeHandler:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunSchemeTest(g_handler->GetBrowser()); +} + +// Sent by the default notification center immediately before the application +// terminates. +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Shut down CEF. + g_handler = NULL; + CefShutdown(); + + [self release]; +} + +@end + + +int main(int argc, char* argv[]) +{ + // Retrieve the current working directory. + getcwd(szWorkingDir, sizeof(szWorkingDir)); + + // Initialize CEF. This will also create the NSApplication instance. + CefInitialize(false, std::wstring()); + + // Initialize tests. + InitExtensionTest(); + InitSchemeTest(); + + // Create the application delegate and window. + NSObject* delegate = [[ClientAppDelegate alloc] init]; + [delegate performSelectorOnMainThread:@selector(createApp:) withObject:nil + waitUntilDone:NO]; + + // Run the application message loop. + [NSApp run]; + + // Don't put anything below this line because it won't be executed. + return 0; +} + + +// ClientHandler implementation + +CefHandler::RetVal ClientHandler::HandleAddressChange( + CefRefPtr browser, CefRefPtr frame, + const std::wstring& url) +{ + if(m_BrowserHwnd == browser->GetWindowHandle() && frame->IsMain()) + { + // Set the edit window text + NSTextField* textField = (NSTextField*)m_EditHwnd; + NSString* str = WStringToNSString(url); + [textField setStringValue:str]; + [str release]; + } + return RV_CONTINUE; +} + +CefHandler::RetVal ClientHandler::HandleTitleChange( + CefRefPtr browser, const std::wstring& title) +{ + // Set the frame window title bar + NSWindow* window = (NSWindow*)m_MainHwnd; + NSString* str = WStringToNSString(title); + [window setTitle:str]; + [str release]; + return RV_CONTINUE; +} + +CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad( + CefRefPtr browser, CefRefPtr request, + std::wstring& redirectUrl, CefRefPtr& resourceStream, + std::wstring& mimeType, int loadFlags) +{ + std::wstring url = request->GetURL(); + if(url == L"http://tests/request") { + // Show the request contents + std::wstring dump; + DumpRequestContents(request, dump); + resourceStream = CefStreamReader::CreateForData( + (void*)dump.c_str(), dump.size() * sizeof(wchar_t)); + mimeType = L"text/plain"; + } + return RV_CONTINUE; +} + +void ClientHandler::SendNotification(NotificationType type) +{ + SEL sel = nil; + switch(type) { + case NOTIFY_CONSOLE_MESSAGE: + sel = @selector(notifyConsoleMessage:); + break; + case NOTIFY_DOWNLOAD_COMPLETE: + sel = @selector(notifyDownloadComplete:); + break; + case NOTIFY_DOWNLOAD_ERROR: + sel = @selector(notifyDownloadError:); + break; + } + + if(sel == nil) + return; + + NSWindow* window = (NSWindow*)g_handler->GetMainHwnd(); + NSObject* delegate = [window delegate]; + [delegate performSelectorOnMainThread:sel withObject:nil waitUntilDone:NO]; +} + + +// Global functions + +std::wstring AppGetWorkingDirectory() +{ + return StringToWString(szWorkingDir); +} diff --git a/tests/cefclient/download_handler.cpp b/tests/cefclient/download_handler.cpp index 3bbc2e110..47c5b9aeb 100644 --- a/tests/cefclient/download_handler.cpp +++ b/tests/cefclient/download_handler.cpp @@ -169,7 +169,10 @@ public: file_ = _wfopen(ss.str().c_str(), L"wb"); ASSERT(file_ != NULL); } -#endif // _WIN32 +#else + // TODO(port): Implement this. + ASSERT(false); // Not implemented +#endif } void OnComplete() diff --git a/tests/cefclient/scheme_test.cpp b/tests/cefclient/scheme_test.cpp index f4a6cd020..60d6849b1 100644 --- a/tests/cefclient/scheme_test.cpp +++ b/tests/cefclient/scheme_test.cpp @@ -38,16 +38,21 @@ public: // Build the response html html_ = "Client Scheme Handler" "This contents of this page page are served by the " - "ClientSchemeHandler class handling the client:// protocol." - "
You should see an image:" - "
";
+              "ClientSchemeHandler class handling the client:// protocol.";
+      
+#ifdef _WIN32
+      html_.append("
You should see an image:" + "
"); +#endif // _WIN32 + + html_.append("
");
       
       // Output a string representation of the request
       std::wstring dump;
       DumpRequestContents(request, dump);
       html_.append(WStringToString(dump));
 
-      html_.append("

Try the test form:" + html_.append("

Try the test form:" "
" "" "" @@ -56,7 +61,7 @@ public: handled = true; size_ = html_.size(); - bytes_ = (LPBYTE)html_.c_str(); + bytes_ = html_.c_str(); // Set the resulting mime type mime_type = L"text/html"; @@ -64,7 +69,11 @@ public: #ifdef _WIN32 else if(wcsstr(url.c_str(), L"client.gif") != NULL) { // Load the response image - if(LoadBinaryResource(IDS_LOGO, size_, bytes_)) { + DWORD dwSize; + LPBYTE pBytes; + if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) { + size_ = dwSize; + bytes_ = reinterpret_cast(pBytes); handled = true; // Set the resulting mime type mime_type = L"image/jpg"; @@ -97,7 +106,8 @@ public: if(offset_ < size_) { // Copy the next block of data into the buffer. - int transfer_size = min(bytes_to_read, static_cast(size_ - offset_)); + int transfer_size = + std::min(bytes_to_read, static_cast(size_ - offset_)); memcpy(data_out, bytes_ + offset_, transfer_size); offset_ += transfer_size; @@ -111,8 +121,8 @@ public: } private: - DWORD size_, offset_; - LPBYTE bytes_; + size_t size_, offset_; + const char* bytes_; std::string html_; }; diff --git a/tests/cefclient/string_util_mac.h b/tests/cefclient/string_util_mac.h new file mode 100644 index 000000000..dbde7966f --- /dev/null +++ b/tests/cefclient/string_util_mac.h @@ -0,0 +1,22 @@ +// Copyright (c) 2010 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. + +#ifndef _CEFCLIENT_STRING_UTIL_MAC_H +#define _CEFCLIENT_STRING_UTIL_MAC_H + +#if defined(__APPLE__) + +#include +#import + +// Convert a std::wstring to an NSString. The NSString must be released by the +// caller. +NSString* WStringToNSString(const std::wstring& str); + +// Convert an NSString to a std::wstring. +std::wstring NSStringToWString(NSString* str); + +#endif // defined(__APPLE__) + +#endif // _CEFCLIENT_STRING_UTIL_MAC_H diff --git a/tests/cefclient/string_util_mac.mm b/tests/cefclient/string_util_mac.mm new file mode 100644 index 000000000..f19ab5147 --- /dev/null +++ b/tests/cefclient/string_util_mac.mm @@ -0,0 +1,47 @@ +// Copyright (c) 2010 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 "string_util.h" +#include "string_util_mac.h" +#include "util.h" + +#if defined(__APPLE__) + +#if TARGET_RT_BIG_ENDIAN +#define WCHAR_T_ENCODING NSUTF32BigEndianStringEncoding +#else +#define WCHAR_T_ENCODING NSUTF32LittleEndianStringEncoding +#endif + +std::wstring StringToWString(const std::string& s) +{ + NSString* nsstr = [[NSString alloc] initWithCString:s.c_str()]; + std::wstring wstr = NSStringToWString(nsstr); + [nsstr release]; + return wstr; +} + +std::string WStringToString(const std::wstring& s) +{ + NSString* nsstr = WStringToNSString(s); + std::string str = [nsstr UTF8String]; + [nsstr release]; + return str; +} + +NSString* WStringToNSString(const std::wstring& str) +{ + return [[NSString alloc] initWithBytes:(void*)str.c_str() + length:str.length()*4 + encoding:WCHAR_T_ENCODING]; +} + +std::wstring NSStringToWString(NSString* str) +{ + NSData* data = [str dataUsingEncoding:WCHAR_T_ENCODING]; + return std::wstring((wchar_t*)[data bytes], + [data length] / sizeof(wchar_t)); +} + +#endif // defined(__APPLE__) diff --git a/tests/cefclient/util.h b/tests/cefclient/util.h index 1b334f603..12bbefc1c 100644 --- a/tests/cefclient/util.h +++ b/tests/cefclient/util.h @@ -42,6 +42,18 @@ code \ MSVC_POP_WARNING() -#endif // _WIN32 +#else // !_WIN32 + +#include + +#ifdef _DEBUG +#define ASSERT(condition) if(!(condition)) { assert(false); } +#else +#define ASSERT(condition) ((void)0) +#endif + +#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code + +#endif // !_WIN32 #endif // _CEFCLIENT_UTIL_H diff --git a/tests/unittests/request_unittest.cc b/tests/unittests/request_unittest.cc index 15b660ea9..4b57462ff 100644 --- a/tests/unittests/request_unittest.cc +++ b/tests/unittests/request_unittest.cc @@ -46,6 +46,8 @@ static void VerifyPostDataElementEqual(CefRefPtr elem1, case PDE_TYPE_FILE: ASSERT_EQ(elem1->GetFile(), elem2->GetFile()); break; + default: + break; } } @@ -128,19 +130,19 @@ TEST(RequestTest, SetGet) // CefPostData AddElement postData->AddElement(element1); postData->AddElement(element2); - ASSERT_EQ(2, postData->GetElementCount()); + ASSERT_EQ((size_t)2, postData->GetElementCount()); // CefPostData RemoveElement postData->RemoveElement(element1); - ASSERT_EQ(1, postData->GetElementCount()); + ASSERT_EQ((size_t)1, postData->GetElementCount()); // CefPostData RemoveElements postData->RemoveElements(); - ASSERT_EQ(0, postData->GetElementCount()); + ASSERT_EQ((size_t)0, postData->GetElementCount()); postData->AddElement(element1); postData->AddElement(element2); - ASSERT_EQ(2, postData->GetElementCount()); + ASSERT_EQ((size_t)2, postData->GetElementCount()); CefPostData::ElementVector elements; postData->GetElements(elements); CefPostData::ElementVector::const_iterator it = elements.begin(); diff --git a/tests/unittests/stream_unittest.cc b/tests/unittests/stream_unittest.cc index 8a8047b9d..08c771bca 100644 --- a/tests/unittests/stream_unittest.cc +++ b/tests/unittests/stream_unittest.cc @@ -5,8 +5,6 @@ #include "include/cef.h" #include "testing/gtest/include/gtest/gtest.h" -#define min(a,b) ((a)<(b)?(a):(b)) - static void VerifyStreamReadBehavior(CefRefPtr stream, const std::string& contents) { @@ -29,7 +27,7 @@ static void VerifyStreamReadBehavior(CefRefPtr stream, char buff[10]; int res, read, offset = 0; do { - read = min(sizeof(buff), contentSize-offset); + read = std::min((int)sizeof(buff), contentSize-offset); res = stream->Read(buff, 1, read); ASSERT_EQ(read, res); ASSERT_TRUE(!memcmp(contentStr+offset, buff, res)); @@ -50,7 +48,7 @@ static void VerifyStreamWriteBehavior(CefRefPtr stream, // Write 10 characters at a time and verify the result int res, write, offset = 0; do { - write = min(10, contentSize-offset); + write = std::min(10, contentSize-offset); res = stream->Write(contentStr+offset, 1, write); ASSERT_EQ(write, res); offset += res; @@ -72,18 +70,24 @@ static void VerifyStreamWriteBehavior(CefRefPtr stream, TEST(StreamTest, ReadFile) { - std::wstring fileName = L"StreamTest.VerifyReadFile.txt"; + const char* fileName = "StreamTest.VerifyReadFile.txt"; + std::wstring fileNameStr = L"StreamTest.VerifyReadFile.txt"; std::string contents = "This is my test\ncontents for the file"; // Create the file FILE* f = NULL; - _wfopen_s(&f, fileName.c_str(), L"wb"); +#ifdef _WIN32 + fopen_s(&f, fileName, "wb"); +#else + f = fopen(fileName, "wb"); +#endif ASSERT_TRUE(f != NULL); - ASSERT_EQ(1, fwrite(contents.c_str(), contents.size(), 1, f)); + ASSERT_EQ((size_t)1, fwrite(contents.c_str(), contents.size(), 1, f)); fclose(f); // Test the stream - CefRefPtr stream(CefStreamReader::CreateForFile(fileName)); + CefRefPtr stream( + CefStreamReader::CreateForFile(fileNameStr)); ASSERT_TRUE(stream.get() != NULL); VerifyStreamReadBehavior(stream, contents); @@ -91,7 +95,11 @@ TEST(StreamTest, ReadFile) stream = NULL; // Delete the file - ASSERT_EQ(0, _wunlink(fileName.c_str())); +#ifdef _WIN32 + ASSERT_EQ(0, _unlink(fileName)); +#else + ASSERT_EQ(0, unlink(fileName)); +#endif } TEST(StreamTest, ReadData) @@ -107,11 +115,13 @@ TEST(StreamTest, ReadData) TEST(StreamTest, WriteFile) { - std::wstring fileName = L"StreamTest.VerifyWriteFile.txt"; + const char* fileName = "StreamTest.VerifyWriteFile.txt"; + std::wstring fileNameStr = L"StreamTest.VerifyWriteFile.txt"; std::string contents = "This is my test\ncontents for the file"; // Test the stream - CefRefPtr stream(CefStreamWriter::CreateForFile(fileName)); + CefRefPtr stream( + CefStreamWriter::CreateForFile(fileNameStr)); ASSERT_TRUE(stream.get() != NULL); VerifyStreamWriteBehavior(stream, contents); @@ -121,9 +131,13 @@ TEST(StreamTest, WriteFile) // Read the file that was written FILE* f = NULL; char* buff = new char[contents.size()]; - _wfopen_s(&f, fileName.c_str(), L"rb"); +#ifdef _WIN32 + fopen_s(&f, fileName, "rb"); +#else + f = fopen(fileName, "rb"); +#endif ASSERT_TRUE(f != NULL); - ASSERT_EQ(1, fread(buff, contents.size(), 1, f)); + ASSERT_EQ((size_t)1, fread(buff, contents.size(), 1, f)); // Read past the end of the file fgetc(f); @@ -135,7 +149,11 @@ TEST(StreamTest, WriteFile) delete [] buff; // Delete the file - ASSERT_EQ(0, _wunlink(fileName.c_str())); +#ifdef _WIN32 + ASSERT_EQ(0, _unlink(fileName)); +#else + ASSERT_EQ(0, unlink(fileName)); +#endif } bool g_ReadHandlerTesterDeleted = false; @@ -206,12 +224,12 @@ TEST(StreamTest, ReadHandler) ASSERT_TRUE(stream.get() != NULL); // CefReadHandler Read - char* read_ptr = "My data"; + const char* read_ptr = "My data"; size_t read_size = sizeof(read_ptr); size_t read_n = 1; - size_t read_res = stream->Read(read_ptr, read_size, read_n); + size_t read_res = stream->Read((void*)read_ptr, read_size, read_n); ASSERT_TRUE(handler->read_called_); - ASSERT_EQ(10, read_res); + ASSERT_EQ((size_t)10, read_res); ASSERT_EQ(read_ptr, handler->read_ptr_); ASSERT_EQ(read_size, handler->read_size_); ASSERT_EQ(read_n, handler->read_n_); @@ -310,12 +328,12 @@ TEST(StreamTest, WriteHandler) ASSERT_TRUE(stream.get() != NULL); // CefWriteHandler Write - char* write_ptr = "My data"; + const char* write_ptr = "My data"; size_t write_size = sizeof(write_ptr); size_t write_n = 1; size_t write_res = stream->Write(write_ptr, write_size, write_n); ASSERT_TRUE(handler->write_called_); - ASSERT_EQ(10, write_res); + ASSERT_EQ((size_t)10, write_res); ASSERT_EQ(write_ptr, handler->write_ptr_); ASSERT_EQ(write_size, handler->write_size_); ASSERT_EQ(write_n, handler->write_n_); diff --git a/tests/unittests/test_handler.h b/tests/unittests/test_handler.h index 8dfa6d9f8..dff0c9cac 100644 --- a/tests/unittests/test_handler.h +++ b/tests/unittests/test_handler.h @@ -251,7 +251,7 @@ public: return browser_; } - HWND GetBrowserHwnd() + CefWindowHandle GetBrowserHwnd() { return browser_hwnd_; } diff --git a/tests/unittests/v8_unittest.cc b/tests/unittests/v8_unittest.cc index bf9ffb0a6..8eadc9c4a 100644 --- a/tests/unittests/v8_unittest.cc +++ b/tests/unittests/v8_unittest.cc @@ -33,7 +33,7 @@ public: if(name == L"execute") { g_V8TestV8HandlerExecuteCalled = true; - ASSERT_EQ(8, arguments.size()); + ASSERT_EQ((size_t)8, arguments.size()); int argct = 0; // basic types @@ -203,7 +203,7 @@ public: g_V8TestV8HandlerExecute2Called = true; // check the result of calling the "execute" function - ASSERT_EQ(1, arguments.size()); + ASSERT_EQ((size_t)1, arguments.size()); ASSERT_TRUE(arguments[0]->IsInt()); ASSERT_EQ(5, arguments[0]->GetIntValue()); } diff --git a/tests/unittests/xml_reader_unittest.cc b/tests/unittests/xml_reader_unittest.cc index 5031103a5..b64f7b3c9 100644 --- a/tests/unittests/xml_reader_unittest.cc +++ b/tests/unittests/xml_reader_unittest.cc @@ -69,7 +69,7 @@ TEST(XmlReaderTest, Read) ASSERT_EQ(reader->GetQualifiedName(), L"ns:obj"); ASSERT_EQ(reader->GetNamespaceURI(), L"http://www.example.org/ns"); ASSERT_TRUE(reader->HasAttributes()); - ASSERT_EQ(reader->GetAttributeCount(), 1); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)1); ASSERT_EQ(reader->GetAttribute(0), L"http://www.example.org/ns"); ASSERT_EQ(reader->GetAttribute(L"xmlns:ns"), L"http://www.example.org/ns"); ASSERT_EQ(reader->GetAttribute(L"ns", L"http://www.w3.org/2000/xmlns/"), @@ -356,7 +356,7 @@ TEST(XmlReaderTest, Read) ASSERT_TRUE(reader->IsEmptyElement()); ASSERT_TRUE(reader->HasAttributes()); ASSERT_FALSE(reader->HasValue()); - ASSERT_EQ(reader->GetAttributeCount(), 2); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)2); ASSERT_EQ(reader->GetAttribute(0), L"value C1"); ASSERT_EQ(reader->GetAttribute(L"ns:attr1"), L"value C1"); ASSERT_EQ(reader->GetAttribute(L"attr1", L"http://www.example.org/ns"), @@ -486,7 +486,7 @@ TEST(XmlReaderTest, Read) // Strangely, the end node will report if the starting node has attributes // but will not provide access to them. ASSERT_TRUE(reader->HasAttributes()); - ASSERT_EQ(reader->GetAttributeCount(), 0); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)0); // And we're done. ASSERT_FALSE(reader->MoveToNextNode()); @@ -532,12 +532,12 @@ TEST(XmlReaderTest, ObjectLoad) ASSERT_FALSE(object->HasAttributes()); ASSERT_TRUE(object->HasChildren()); - ASSERT_EQ(object->GetChildCount(), 1); + ASSERT_EQ(object->GetChildCount(), (size_t)1); CefRefPtr obj(object->FindChild(L"ns:obj")); ASSERT_TRUE(obj.get()); ASSERT_TRUE(obj->HasChildren()); - ASSERT_EQ(obj->GetChildCount(), 4); + ASSERT_EQ(obj->GetChildCount(), (size_t)4); CefRefPtr obj_child(obj->FindChild(L"ns:objC")); ASSERT_TRUE(obj_child.get()); @@ -547,8 +547,8 @@ TEST(XmlReaderTest, ObjectLoad) ASSERT_TRUE(obj_child->HasAttributes()); CefXmlObject::ObjectVector obj_children; - ASSERT_EQ(obj->GetChildren(obj_children), 4); - ASSERT_EQ(obj_children.size(), 4); + ASSERT_EQ(obj->GetChildren(obj_children), (size_t)4); + ASSERT_EQ(obj_children.size(), (size_t)4); CefXmlObject::ObjectVector::const_iterator it = obj_children.begin(); for (int ct = 0; it != obj_children.end(); ++it, ++ct) { @@ -567,7 +567,7 @@ TEST(XmlReaderTest, ObjectLoad) ASSERT_TRUE(obj_child->HasChildren()); ASSERT_FALSE(obj_child->HasValue()); ASSERT_FALSE(obj_child->HasAttributes()); - ASSERT_EQ(obj_child->GetChildCount(), 4); + ASSERT_EQ(obj_child->GetChildCount(), (size_t)4); obj_child = obj_child->FindChild(L"ns:objB_4"); ASSERT_TRUE(obj_child.get()); ASSERT_TRUE(obj_child->HasValue()); @@ -581,12 +581,12 @@ TEST(XmlReaderTest, ObjectLoad) ASSERT_TRUE(obj_child->HasAttributes()); CefXmlObject::AttributeMap attribs; - ASSERT_EQ(obj_child->GetAttributes(attribs), 2); - ASSERT_EQ(attribs.size(), 2); + ASSERT_EQ(obj_child->GetAttributes(attribs), (size_t)2); + ASSERT_EQ(attribs.size(), (size_t)2); ASSERT_EQ(attribs[L"ns:attr1"], L"value C1"); ASSERT_EQ(attribs[L"ns:attr2"], L"value C2"); - ASSERT_EQ(obj_child->GetAttributeCount(), 2); + ASSERT_EQ(obj_child->GetAttributeCount(), (size_t)2); ASSERT_TRUE(obj_child->HasAttribute(L"ns:attr1")); ASSERT_EQ(obj_child->GetAttributeValue(L"ns:attr1"), L"value C1"); ASSERT_TRUE(obj_child->HasAttribute(L"ns:attr2")); diff --git a/tests/unittests/zip_reader_unittest.cc b/tests/unittests/zip_reader_unittest.cc index 995650d19..ae2a3c6cb 100644 --- a/tests/unittests/zip_reader_unittest.cc +++ b/tests/unittests/zip_reader_unittest.cc @@ -222,7 +222,7 @@ TEST(ZipReaderTest, ReadArchive) // Create the Zip archive object. CefRefPtr archive(new CefZipArchive()); - ASSERT_EQ(archive->Load(stream, false), 5); + ASSERT_EQ(archive->Load(stream, false), (size_t)5); ASSERT_TRUE(archive->HasFile(L"test_archive/file 1.txt")); ASSERT_TRUE(archive->HasFile(L"test_archive/folder 1/file 1a.txt")); @@ -235,7 +235,7 @@ TEST(ZipReaderTest, ReadArchive) file = archive->GetFile(L"test_archive/folder 2/file 2a.txt"); ASSERT_TRUE(file.get()); - ASSERT_EQ(file->GetDataSize(), 20); + ASSERT_EQ(file->GetDataSize(), (size_t)20); ASSERT_TRUE(!strncmp(reinterpret_cast(file->GetData()), "Contents of file 2A.", 20)); @@ -244,11 +244,11 @@ TEST(ZipReaderTest, ReadArchive) ASSERT_TRUE(reader.get()); char buff[8]; - ASSERT_EQ(reader->Read(buff, 1, 8), 8); + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)8); ASSERT_TRUE(!strncmp(buff, "Contents", 8)); - ASSERT_EQ(reader->Read(buff, 1, 8), 8); + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)8); ASSERT_TRUE(!strncmp(buff, " of file", 8)); - ASSERT_EQ(reader->Read(buff, 1, 8), 4); + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)4); ASSERT_TRUE(!strncmp(buff, " 2A.", 4)); ASSERT_TRUE(reader->Eof()); }