mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
cef linux64 2454
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@64340 954022d7-b5bf-4e40-9824-e11837661b57
This commit is contained in:
committed by
Alexander Trofimov
parent
44f3ab4124
commit
a8deb86c9c
81
.gitattributes
vendored
81
.gitattributes
vendored
@ -689,6 +689,69 @@ DesktopEditor/ChromiumBasedEditors svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2 svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64 svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_100_percent.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_200_percent.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_extensions.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/chrome-sandbox svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/devtools_resources.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/icudtl.dat svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/am.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ar.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/bg.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/bn.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ca.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/cs.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/da.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/de.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/el.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/en-GB.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/en-US.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/es-419.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/es.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/et.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fa.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fi.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fil.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fr.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/gu.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/he.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hi.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hr.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hu.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/id.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/it.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ja.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/kn.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ko.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/lt.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/lv.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ml.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/mr.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ms.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/nb.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/nl.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pl.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pt-BR.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pt-PT.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ro.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ru.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sk.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sl.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sr.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sv.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sw.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ta.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/te.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/th.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/tr.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/uk.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/vi.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/zh-CN.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/zh-TW.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/snapshot_blob.bin svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32 svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32/cef.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32/cef_100_percent.pak svn_mime_002dtype=application%2Foctet-stream
|
||||
@ -896,6 +959,24 @@ DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/qcefview svnc_tsvn_003alogminsize=
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/browser svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/common svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/renderer svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources/logo.png svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources/pdf.pdf svn_mime_002dtype=application%2Foctet-stream
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/base svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/base/internal svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/capi svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/internal svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/wrapper svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/base svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/cpptoc svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/ctocpp svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/wrapper svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/mac svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/windows svnc_tsvn_003alogminsize=5
|
||||
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/windows/cefclient svnc_tsvn_003alogminsize=5
|
||||
|
||||
@ -0,0 +1,421 @@
|
||||
# Copyright (c) 2014 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.
|
||||
|
||||
#
|
||||
# Source files.
|
||||
#
|
||||
|
||||
# cefclient browser sources.
|
||||
set(CEFCLIENT_BROWSER_BROWSER_SRCS
|
||||
browser/binding_test.cc
|
||||
browser/binding_test.h
|
||||
browser/browser_window.cc
|
||||
browser/browser_window.h
|
||||
browser/bytes_write_handler.cc
|
||||
browser/bytes_write_handler.h
|
||||
browser/client_app_browser.cc
|
||||
browser/client_app_browser.h
|
||||
browser/client_app_delegates_browser.cc
|
||||
browser/client_handler.cc
|
||||
browser/client_handler.h
|
||||
browser/client_handler_osr.cc
|
||||
browser/client_handler_osr.h
|
||||
browser/client_handler_std.cc
|
||||
browser/client_handler_std.h
|
||||
browser/client_types.h
|
||||
browser/dialog_test.cc
|
||||
browser/dialog_test.h
|
||||
browser/geometry_util.cc
|
||||
browser/geometry_util.h
|
||||
browser/main_context.cc
|
||||
browser/main_context.h
|
||||
browser/main_context_impl.cc
|
||||
browser/main_context_impl.h
|
||||
browser/main_message_loop.cc
|
||||
browser/main_message_loop.h
|
||||
browser/main_message_loop_std.cc
|
||||
browser/main_message_loop_std.h
|
||||
browser/osr_dragdrop_events.h
|
||||
browser/osr_renderer.cc
|
||||
browser/osr_renderer.h
|
||||
browser/resource.h
|
||||
browser/resource_util.h
|
||||
browser/root_window.cc
|
||||
browser/root_window.h
|
||||
browser/root_window_manager.cc
|
||||
browser/root_window_manager.h
|
||||
browser/scheme_test.cc
|
||||
browser/scheme_test.h
|
||||
browser/temp_window.h
|
||||
browser/test_runner.cc
|
||||
browser/test_runner.h
|
||||
browser/urlrequest_test.cc
|
||||
browser/urlrequest_test.h
|
||||
browser/window_test.cc
|
||||
browser/window_test.h
|
||||
)
|
||||
source_group(cefclient\\\\browser FILES ${CEFCLIENT_BROWSER_BROWSER_SRCS})
|
||||
|
||||
set(CEFCLIENT_BROWSER_SRCS
|
||||
${CEFCLIENT_BROWSER_BROWSER_SRCS}
|
||||
)
|
||||
|
||||
# cefclient common sources.
|
||||
set(CEFCLIENT_COMMON_COMMON_SRCS
|
||||
common/client_app.cc
|
||||
common/client_app.h
|
||||
common/client_app_delegates_common.cc
|
||||
common/client_app_other.cc
|
||||
common/client_app_other.h
|
||||
common/client_switches.cc
|
||||
common/client_switches.h
|
||||
common/scheme_test_common.cc
|
||||
common/scheme_test_common.h
|
||||
)
|
||||
source_group(cefclient\\\\common FILES ${CEFCLIENT_COMMON_COMMON_SRCS})
|
||||
|
||||
set(CEFCLIENT_COMMON_SRCS
|
||||
${CEFCLIENT_COMMON_COMMON_SRCS}
|
||||
)
|
||||
|
||||
# cefclient renderer sources.
|
||||
set(CEFCLIENT_RENDERER_RENDERER_SRCS
|
||||
renderer/client_app_delegates_renderer.cc
|
||||
renderer/client_app_renderer.cc
|
||||
renderer/client_app_renderer.h
|
||||
renderer/client_renderer.cc
|
||||
renderer/client_renderer.h
|
||||
renderer/performance_test.cc
|
||||
renderer/performance_test.h
|
||||
renderer/performance_test_setup.h
|
||||
renderer/performance_test_tests.cc
|
||||
)
|
||||
source_group(cefclient\\\\renderer FILES ${CEFCLIENT_RENDERER_RENDERER_SRCS})
|
||||
|
||||
set(CEFCLIENT_RENDERER_SRCS
|
||||
${CEFCLIENT_RENDERER_RENDERER_SRCS}
|
||||
)
|
||||
|
||||
#cefclient Linux sources
|
||||
set(CEFCLIENT_LINUX_SRCS
|
||||
cefclient_gtk.cc
|
||||
)
|
||||
source_group(cefclient FILES ${CEFCLIENT_LINUX_SRCS})
|
||||
|
||||
set(CEFCLIENT_LINUX_BROWSER_SRCS
|
||||
browser/browser_window_osr_gtk.cc
|
||||
browser/browser_window_osr_gtk.h
|
||||
browser/browser_window_std_gtk.cc
|
||||
browser/browser_window_std_gtk.h
|
||||
browser/dialog_handler_gtk.cc
|
||||
browser/dialog_handler_gtk.h
|
||||
browser/main_context_impl_posix.cc
|
||||
browser/print_handler_gtk.cc
|
||||
browser/print_handler_gtk.h
|
||||
browser/resource_util_linux.cc
|
||||
browser/resource_util_posix.cc
|
||||
browser/root_window_gtk.cc
|
||||
browser/root_window_gtk.h
|
||||
browser/temp_window_x11.cc
|
||||
browser/temp_window_x11.h
|
||||
browser/window_test_gtk.cc
|
||||
)
|
||||
source_group(cefclient\\\\browser FILES ${CEFCLIENT_LINUX_BROWSER_SRCS})
|
||||
|
||||
set(CEFCLIENT_LINUX_SRCS
|
||||
${CEFCLIENT_LINUX_SRCS}
|
||||
${CEFCLIENT_LINUX_BROWSER_SRCS}
|
||||
)
|
||||
|
||||
#cefclient Mac OS X sources
|
||||
set(CEFCLIENT_MACOSX_SRCS
|
||||
cefclient_mac.mm
|
||||
)
|
||||
source_group(cefclient FILES ${CEFCLIENT_MACOSX_SRCS})
|
||||
|
||||
set(CEFCLIENT_MACOSX_BROWSER_SRCS
|
||||
browser/browser_window_osr_mac.h
|
||||
browser/browser_window_osr_mac.mm
|
||||
browser/browser_window_std_mac.h
|
||||
browser/browser_window_std_mac.mm
|
||||
browser/main_context_impl_posix.cc
|
||||
browser/resource_util_mac.mm
|
||||
browser/resource_util_posix.cc
|
||||
browser/root_window_mac.h
|
||||
browser/root_window_mac.mm
|
||||
browser/temp_window_mac.h
|
||||
browser/temp_window_mac.mm
|
||||
browser/window_test_mac.mm
|
||||
)
|
||||
source_group(cefclient\\\\browser FILES ${CEFCLIENT_MACOSX_BROWSER_SRCS})
|
||||
|
||||
set(CEFCLIENT_MACOSX_SRCS
|
||||
${CEFCLIENT_MACOSX_SRCS}
|
||||
${CEFCLIENT_MACOSX_BROWSER_SRCS}
|
||||
)
|
||||
|
||||
# cefclient Mac OS X helper sources.
|
||||
set(CEFCLIENT_HELPER_SRCS
|
||||
process_helper_mac.cc
|
||||
)
|
||||
source_group(cefclient FILES ${CEFCLIENT_HELPER_SRCS})
|
||||
|
||||
set(CEFCLIENT_MACOSX_HELPER_SRCS
|
||||
${CEFCLIENT_HELPER_SRCS}
|
||||
)
|
||||
|
||||
#cefclient Windows sources
|
||||
set(CEFCLIENT_WINDOWS_SRCS
|
||||
cefclient_win.cc
|
||||
)
|
||||
source_group(cefclient FILES ${CEFCLIENT_WINDOWS_SRCS})
|
||||
|
||||
set(CEFCLIENT_WINDOWS_BROWSER_SRCS
|
||||
browser/browser_window_osr_win.cc
|
||||
browser/browser_window_osr_win.h
|
||||
browser/browser_window_std_win.cc
|
||||
browser/browser_window_std_win.h
|
||||
browser/main_context_impl_win.cc
|
||||
browser/main_message_loop_multithreaded_win.cc
|
||||
browser/main_message_loop_multithreaded_win.h
|
||||
browser/osr_dragdrop_win.cc
|
||||
browser/osr_dragdrop_win.h
|
||||
browser/osr_window_win.cc
|
||||
browser/osr_window_win.h
|
||||
browser/resource_util_win.cc
|
||||
browser/root_window_win.cc
|
||||
browser/root_window_win.h
|
||||
browser/temp_window_win.cc
|
||||
browser/temp_window_win.h
|
||||
browser/util_win.cc
|
||||
browser/util_win.h
|
||||
browser/window_test_win.cc
|
||||
)
|
||||
source_group(cefclient\\\\browser FILES ${CEFCLIENT_WINDOWS_BROWSER_SRCS})
|
||||
|
||||
set(CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS
|
||||
resources/win/cefclient.exe.manifest
|
||||
resources/win/cefclient.ico
|
||||
resources/win/cefclient.rc
|
||||
resources/win/small.ico
|
||||
)
|
||||
source_group(cefclient\\\\resources\\\\win FILES ${CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS})
|
||||
|
||||
set(CEFCLIENT_WINDOWS_SRCS
|
||||
${CEFCLIENT_WINDOWS_SRCS}
|
||||
${CEFCLIENT_WINDOWS_BROWSER_SRCS}
|
||||
${CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS}
|
||||
)
|
||||
|
||||
# cefclient resources.
|
||||
set(CEFCLIENT_RESOURCES_RESOURCES_SRCS
|
||||
resources/binding.html
|
||||
resources/dialogs.html
|
||||
resources/localstorage.html
|
||||
resources/logo.png
|
||||
resources/osr_test.html
|
||||
resources/other_tests.html
|
||||
resources/pdf.html
|
||||
resources/pdf.pdf
|
||||
resources/performance.html
|
||||
resources/performance2.html
|
||||
resources/transparency.html
|
||||
resources/urlrequest.html
|
||||
resources/window.html
|
||||
resources/xmlhttprequest.html
|
||||
)
|
||||
source_group(cefclient\\\\resources FILES ${CEFCLIENT_RESOURCES_RESOURCES_SRCS})
|
||||
|
||||
set(CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS_MACOSX
|
||||
resources/mac/Info.plist
|
||||
resources/mac/cefclient.icns
|
||||
)
|
||||
APPEND_PLATFORM_SOURCES(CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS)
|
||||
source_group(cefclient\\\\resources\\\\mac FILES ${CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS})
|
||||
|
||||
set(CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS_MACOSX
|
||||
resources/mac/English.lproj/InfoPlist.strings
|
||||
resources/mac/English.lproj/MainMenu.xib
|
||||
)
|
||||
APPEND_PLATFORM_SOURCES(CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS)
|
||||
source_group(cefclient\\\\resources\\\\mac\\\\English.lproj FILES ${CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS})
|
||||
|
||||
set(CEFCLIENT_RESOURCES_SRCS
|
||||
${CEFCLIENT_RESOURCES_RESOURCES_SRCS}
|
||||
${CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS}
|
||||
${CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS}
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Shared configuration.
|
||||
#
|
||||
|
||||
# Target executable names.
|
||||
set(CEF_TARGET "cefclient")
|
||||
if(OS_MACOSX)
|
||||
set(CEF_HELPER_TARGET "cefclient Helper")
|
||||
endif()
|
||||
|
||||
# Logical target used to link the libcef library.
|
||||
ADD_LOGICAL_TARGET("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}")
|
||||
|
||||
# Determine the target output directory.
|
||||
SET_CEF_TARGET_OUT_DIR()
|
||||
|
||||
|
||||
#
|
||||
# Linux configuration.
|
||||
#
|
||||
|
||||
if(OS_LINUX)
|
||||
# All sources required by the "cefclient" target. Generates an executable that
|
||||
# is used for all processes.
|
||||
set(CEFCLIENT_SRCS
|
||||
${CEFCLIENT_BROWSER_SRCS}
|
||||
${CEFCLIENT_COMMON_SRCS}
|
||||
${CEFCLIENT_RENDERER_SRCS}
|
||||
${CEFCLIENT_RESOURCES_SRCS}
|
||||
${CEFCLIENT_LINUX_SRCS}
|
||||
)
|
||||
|
||||
# Find required libraries and update compiler/linker variables.
|
||||
FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0 gtkglext-1.0")
|
||||
|
||||
# Executable target.
|
||||
add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS})
|
||||
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
|
||||
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
|
||||
|
||||
# Set rpath so that libraries can be placed next to the executable.
|
||||
set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||
set_target_properties(${CEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
set_target_properties(${CEF_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
|
||||
|
||||
# Copy CEF binary and resource files to the target output directory.
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
|
||||
# Copy cefclient resource files to the target output directory.
|
||||
COPY_FILES("${CEF_TARGET}" "${CEFCLIENT_RESOURCES_SRCS}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
# Rename the "res" directory to "files".
|
||||
RENAME_DIRECTORY("${CEF_TARGET}" "${CEF_TARGET_OUT_DIR}/resources" "${CEF_TARGET_OUT_DIR}/files")
|
||||
|
||||
# Set SUID permissions on the chrome-sandbox target.
|
||||
SET_LINUX_SUID_PERMISSIONS("${CEF_TARGET}" "${CEF_TARGET_OUT_DIR}/chrome-sandbox")
|
||||
endif()
|
||||
|
||||
|
||||
#
|
||||
# Mac OS X configuration.
|
||||
#
|
||||
|
||||
if(OS_MACOSX)
|
||||
# All sources required by the "cefclient" target. Generates an app bundle that
|
||||
# is used only for the browser process.
|
||||
set(CEFCLIENT_SRCS
|
||||
${CEFCLIENT_BROWSER_SRCS}
|
||||
${CEFCLIENT_COMMON_SRCS}
|
||||
${CEFCLIENT_RESOURCES_SRCS}
|
||||
${CEFCLIENT_MACOSX_SRCS}
|
||||
)
|
||||
|
||||
# All sources required by the "cefclient Helper" target. Generates an app
|
||||
# bundle that is used only for non-browser processes.
|
||||
set(CEFCLIENT_HELPER_SRCS
|
||||
${CEFCLIENT_COMMON_SRCS}
|
||||
${CEFCLIENT_RENDERER_SRCS}
|
||||
${CEFCLIENT_MACOSX_HELPER_SRCS}
|
||||
)
|
||||
|
||||
# Output paths for the app bundles.
|
||||
set(CEF_APP "${CEF_TARGET_OUT_DIR}/${CEF_TARGET}.app")
|
||||
set(CEF_HELPER_APP "${CEF_TARGET_OUT_DIR}/${CEF_HELPER_TARGET}.app")
|
||||
|
||||
# Variable referenced from Info.plist files.
|
||||
set(PRODUCT_NAME "${CEF_TARGET}")
|
||||
|
||||
# Helper executable target.
|
||||
add_executable(${CEF_HELPER_TARGET} MACOSX_BUNDLE ${CEFCLIENT_HELPER_SRCS})
|
||||
add_dependencies(${CEF_HELPER_TARGET} libcef_dll_wrapper)
|
||||
target_link_libraries(${CEF_HELPER_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
|
||||
set_target_properties(${CEF_HELPER_TARGET} PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/mac/helper-Info.plist
|
||||
)
|
||||
|
||||
# Fix the framework link in the helper executable.
|
||||
FIX_MACOSX_HELPER_FRAMEWORK_LINK(${CEF_HELPER_TARGET} ${CEF_HELPER_APP})
|
||||
|
||||
# Main executable target.
|
||||
add_executable(${CEF_TARGET} MACOSX_BUNDLE ${CEFCLIENT_RESOURCES_SRCS} ${CEFCLIENT_SRCS})
|
||||
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}")
|
||||
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} "-framework OpenGL")
|
||||
set_target_properties(${CEF_TARGET} PROPERTIES
|
||||
RESOURCE "${CEFCLIENT_RESOURCES_SRCS}"
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/mac/Info.plist
|
||||
)
|
||||
|
||||
# Copy files into the main app bundle.
|
||||
add_custom_command(
|
||||
TARGET ${CEF_TARGET}
|
||||
POST_BUILD
|
||||
# Copy the helper app bundle into the Frameworks directory.
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CEF_HELPER_APP}"
|
||||
"${CEF_APP}/Contents/Frameworks/${CEF_HELPER_TARGET}.app"
|
||||
# Copy the CEF framework into the Frameworks directory.
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CEF_BINARY_DIR}/Chromium Embedded Framework.framework"
|
||||
"${CEF_APP}/Contents/Frameworks/Chromium Embedded Framework.framework"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Fix the framework link in the main executable.
|
||||
FIX_MACOSX_MAIN_FRAMEWORK_LINK(${CEF_TARGET} ${CEF_APP})
|
||||
|
||||
# Make the other helper app bundles.
|
||||
MAKE_MACOSX_HELPERS(${CEF_TARGET} ${CEF_APP})
|
||||
|
||||
if(NOT ${CMAKE_GENERATOR} STREQUAL "Xcode")
|
||||
# Manually process and copy over resource files.
|
||||
# The Xcode generator handles this via the set_target_properties RESOURCE directive.
|
||||
set(PREFIXES "resources/mac/" "resources/") # Remove these prefixes from input file paths.
|
||||
COPY_MACOSX_RESOURCES("${CEFCLIENT_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
#
|
||||
# Windows configuration.
|
||||
#
|
||||
|
||||
if(OS_WINDOWS)
|
||||
# All sources required by the "cefclient" target. Generates an executable that
|
||||
# is used for all processes.
|
||||
set(CEFCLIENT_SRCS
|
||||
${CEFCLIENT_BROWSER_SRCS}
|
||||
${CEFCLIENT_COMMON_SRCS}
|
||||
${CEFCLIENT_RENDERER_SRCS}
|
||||
${CEFCLIENT_RESOURCES_SRCS}
|
||||
${CEFCLIENT_WINDOWS_SRCS}
|
||||
)
|
||||
|
||||
# Executable target.
|
||||
add_executable(${CEF_TARGET} WIN32 ${CEFCLIENT_SRCS})
|
||||
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
|
||||
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} "glu32.lib" "opengl32.lib")
|
||||
|
||||
if(USE_SANDBOX)
|
||||
# Logical target used to link the cef_sandbox library.
|
||||
ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}")
|
||||
target_link_libraries(${CEF_TARGET} cef_sandbox_lib ${CEF_SANDBOX_STANDARD_LIBS})
|
||||
endif()
|
||||
|
||||
# Add the custom manifest files to the executable.
|
||||
ADD_WINDOWS_MANIFEST("${CMAKE_CURRENT_SOURCE_DIR}/resources/win" "${CEF_TARGET}")
|
||||
|
||||
# Copy CEF binary and resource files to the target output directory.
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
endif()
|
||||
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2012 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 "cefclient/browser/binding_test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
|
||||
namespace client {
|
||||
namespace binding_test {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestUrl[] = "http://tests/binding";
|
||||
const char kTestMessageName[] = "BindingTest";
|
||||
|
||||
// Handle messages in the browser process.
|
||||
class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
|
||||
// Called due to cefQuery execution in binding.html.
|
||||
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) OVERRIDE {
|
||||
// Only handle messages from the test URL.
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestUrl) != 0)
|
||||
return false;
|
||||
|
||||
const std::string& message_name = request;
|
||||
if (message_name.find(kTestMessageName) == 0) {
|
||||
// Reverse the string and return.
|
||||
std::string result = message_name.substr(sizeof(kTestMessageName));
|
||||
std::reverse(result.begin(), result.end());
|
||||
callback->Success(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
|
||||
handlers.insert(new Handler());
|
||||
}
|
||||
|
||||
} // namespace binding_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_BROWSER_BINDING_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BINDING_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client {
|
||||
namespace binding_test {
|
||||
|
||||
// Create message handlers. Called from test_runner.cc.
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
|
||||
|
||||
} // namespace binding_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BINDING_TEST_H_
|
||||
@ -0,0 +1,89 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/browser_window.h"
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
BrowserWindow::BrowserWindow(Delegate* delegate)
|
||||
: delegate_(delegate),
|
||||
is_closing_(false) {
|
||||
DCHECK(delegate_);
|
||||
}
|
||||
|
||||
void BrowserWindow::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
}
|
||||
|
||||
float BrowserWindow::GetDeviceScaleFactor() const {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> BrowserWindow::GetBrowser() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return browser_;
|
||||
}
|
||||
|
||||
bool BrowserWindow::IsClosing() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return is_closing_;
|
||||
}
|
||||
|
||||
void BrowserWindow::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!browser_);
|
||||
browser_ = browser;
|
||||
|
||||
delegate_->OnBrowserCreated(browser);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
|
||||
is_closing_ = true;
|
||||
}
|
||||
|
||||
void BrowserWindow::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
|
||||
browser_ = NULL;
|
||||
|
||||
client_handler_->DetachDelegate();
|
||||
client_handler_ = NULL;
|
||||
|
||||
// |this| may be deleted.
|
||||
delegate_->OnBrowserWindowDestroyed();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetAddress(const std::string& url) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnSetAddress(url);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetTitle(const std::string& title) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnSetTitle(title);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetFullscreen(bool fullscreen) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnSetFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
|
||||
}
|
||||
|
||||
void BrowserWindow::OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
delegate_->OnSetDraggableRegions(regions);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_browser.h"
|
||||
#include "cefclient/browser/client_handler.h"
|
||||
#include "cefclient/browser/client_types.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents a native child window hosting a single browser instance. The
|
||||
// methods of this class must be called on the main thread unless otherwise
|
||||
// indicated.
|
||||
class BrowserWindow : public ClientHandler::Delegate {
|
||||
public:
|
||||
// This interface is implemented by the owner of the BrowserWindow. The
|
||||
// methods of this class will be called on the main thread.
|
||||
class Delegate {
|
||||
public:
|
||||
// Called when the browser has been created.
|
||||
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Called when the BrowserWindow has been destroyed.
|
||||
virtual void OnBrowserWindowDestroyed() = 0;
|
||||
|
||||
// Set the window URL address.
|
||||
virtual void OnSetAddress(const std::string& url) = 0;
|
||||
|
||||
// Set the window title.
|
||||
virtual void OnSetTitle(const std::string& title) = 0;
|
||||
|
||||
// Set fullscreen mode.
|
||||
virtual void OnSetFullscreen(bool fullscreen) = 0;
|
||||
|
||||
// Set the loading state.
|
||||
virtual void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) = 0;
|
||||
|
||||
// Set the draggable regions.
|
||||
virtual void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
|
||||
// Create a new browser and native window.
|
||||
virtual void CreateBrowser(ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) = 0;
|
||||
|
||||
// Retrieve the configuration that will be used when creating a popup window.
|
||||
// The popup browser will initially be parented to |temp_handle| which should
|
||||
// be a pre-existing hidden window. The native window will be created later
|
||||
// after the browser has been created. This method may be called on any
|
||||
// thread.
|
||||
virtual void GetPopupConfig(CefWindowHandle temp_handle,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) = 0;
|
||||
|
||||
// Show the popup window with correct parent and bounds in parent coordinates.
|
||||
virtual void ShowPopup(ClientWindowHandle parent_handle,
|
||||
int x, int y, size_t width, size_t height) = 0;
|
||||
|
||||
// Show the window.
|
||||
virtual void Show() = 0;
|
||||
|
||||
// Hide the window.
|
||||
virtual void Hide() = 0;
|
||||
|
||||
// Set the window bounds in parent coordinates.
|
||||
virtual void SetBounds(int x, int y, size_t width, size_t height) = 0;
|
||||
|
||||
// Set focus to the window.
|
||||
virtual void SetFocus(bool focus) = 0;
|
||||
|
||||
// Set the device scale factor. Only used in combination with off-screen
|
||||
// rendering.
|
||||
virtual void SetDeviceScaleFactor(float device_scale_factor);
|
||||
|
||||
// Returns the device scale factor. Only used in combination with off-screen
|
||||
// rendering.
|
||||
virtual float GetDeviceScaleFactor() const;
|
||||
|
||||
// Returns the window handle.
|
||||
virtual ClientWindowHandle GetWindowHandle() const = 0;
|
||||
|
||||
// Returns the browser owned by the window.
|
||||
CefRefPtr<CefBrowser> GetBrowser() const;
|
||||
|
||||
// Returns true if the browser is closing.
|
||||
bool IsClosing() const;
|
||||
|
||||
protected:
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<BrowserWindow>;
|
||||
|
||||
// Constructor may be called on any thread.
|
||||
// |delegate| must outlive this object.
|
||||
explicit BrowserWindow(Delegate* delegate);
|
||||
|
||||
// ClientHandler::Delegate methods.
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBrowserClosing(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
|
||||
Delegate* delegate_;
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
CefRefPtr<ClientHandler> client_handler_;
|
||||
bool is_closing_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/browser_window.h"
|
||||
#include "cefclient/browser/client_handler_osr.h"
|
||||
#include "cefclient/browser/osr_renderer.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents a native child window hosting a single off-screen browser
|
||||
// instance. The methods of this class must be called on the main thread unless
|
||||
// otherwise indicated.
|
||||
class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
public ClientHandlerOsr::OsrDelegate {
|
||||
public:
|
||||
// Constructor may be called on any thread.
|
||||
// |delegate| must outlive this object.
|
||||
BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
|
||||
const std::string& startup_url,
|
||||
const OsrRenderer::Settings& settings);
|
||||
|
||||
// BrowserWindow methods.
|
||||
void CreateBrowser(ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) OVERRIDE;
|
||||
void GetPopupConfig(CefWindowHandle temp_handle,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) OVERRIDE;
|
||||
void ShowPopup(ClientWindowHandle parent_handle,
|
||||
int x, int y, size_t width, size_t height) OVERRIDE;
|
||||
void Show() OVERRIDE;
|
||||
void Hide() OVERRIDE;
|
||||
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
|
||||
void SetFocus(bool focus) OVERRIDE;
|
||||
void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
|
||||
// ClientHandlerOsr::OsrDelegate methods.
|
||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE;
|
||||
bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE;
|
||||
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) OVERRIDE;
|
||||
bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefScreenInfo& screen_info) OVERRIDE;
|
||||
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
|
||||
void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) OVERRIDE;
|
||||
void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer,
|
||||
int width,
|
||||
int height) OVERRIDE;
|
||||
void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor,
|
||||
CefRenderHandler::CursorType type,
|
||||
const CefCursorInfo& custom_cursor_info) OVERRIDE;
|
||||
bool StartDragging(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> drag_data,
|
||||
CefRenderHandler::DragOperationsMask allowed_ops,
|
||||
int x, int y) OVERRIDE;
|
||||
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::DragOperation operation) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Create the GTK GlArea.
|
||||
void Create(ClientWindowHandle parent_handle);
|
||||
|
||||
// Signal handlers for the GTK GlArea.
|
||||
static gint SizeAllocation(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static gint ClickEvent(GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static gint KeyEvent(GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static gint MoveEvent(GtkWidget* widget,
|
||||
GdkEventMotion* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static gint ScrollEvent(GtkWidget* widget,
|
||||
GdkEventScroll* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static gint FocusEvent(GtkWidget* widget,
|
||||
GdkEventFocus* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
|
||||
bool IsOverPopupWidget(int x, int y) const;
|
||||
int GetPopupXOffset() const;
|
||||
int GetPopupYOffset() const;
|
||||
void ApplyPopupOffset(int& x, int& y) const;
|
||||
|
||||
void EnableGL();
|
||||
void DisableGL();
|
||||
|
||||
// The below members will only be accessed on the main thread which should be
|
||||
// the same as the CEF UI thread.
|
||||
OsrRenderer renderer_;
|
||||
ClientWindowHandle glarea_;
|
||||
bool hidden_;
|
||||
bool gl_enabled_;
|
||||
bool painting_popup_;
|
||||
|
||||
float device_scale_factor_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_
|
||||
@ -0,0 +1,179 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/browser_window_std_gtk.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#undef Success // Definition conflicts with cef_message_router.h
|
||||
#undef RootWindow // Definition conflicts with root_window.h
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "cefclient/browser/client_handler_std.h"
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
::Window GetXWindowForWidget(GtkWidget* widget) {
|
||||
// The GTK window must be visible before we can retrieve the XID.
|
||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
|
||||
DCHECK(xwindow);
|
||||
return xwindow;
|
||||
}
|
||||
|
||||
void SetXWindowVisible(::Window xwindow, bool visible) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
|
||||
// Retrieve the atoms required by the below XChangeProperty call.
|
||||
const char* kAtoms[] = {
|
||||
"_NET_WM_STATE",
|
||||
"ATOM",
|
||||
"_NET_WM_STATE_HIDDEN"
|
||||
};
|
||||
Atom atoms[3];
|
||||
int result = XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false,
|
||||
atoms);
|
||||
if (!result)
|
||||
NOTREACHED();
|
||||
|
||||
if (!visible) {
|
||||
// Set the hidden property state value.
|
||||
scoped_ptr<Atom[]> data(new Atom[1]);
|
||||
data[0] = atoms[2];
|
||||
|
||||
XChangeProperty(xdisplay,
|
||||
xwindow,
|
||||
atoms[0], // name
|
||||
atoms[1], // type
|
||||
32, // size in bits of items in 'value'
|
||||
PropModeReplace,
|
||||
reinterpret_cast<const unsigned char*>(data.get()),
|
||||
1); // num items
|
||||
} else {
|
||||
// Set an empty array of property state values.
|
||||
XChangeProperty(xdisplay,
|
||||
xwindow,
|
||||
atoms[0], // name
|
||||
atoms[1], // type
|
||||
32, // size in bits of items in 'value'
|
||||
PropModeReplace,
|
||||
NULL,
|
||||
0); // num items
|
||||
}
|
||||
}
|
||||
|
||||
void SetXWindowBounds(::Window xwindow,
|
||||
int x, int y, size_t width, size_t height) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
XWindowChanges changes = {0};
|
||||
changes.x = x;
|
||||
changes.y = y;
|
||||
changes.width = static_cast<int>(width);
|
||||
changes.height = static_cast<int>(height);
|
||||
XConfigureWindow(xdisplay, xwindow,
|
||||
CWX | CWY | CWHeight | CWWidth, &changes);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
|
||||
const std::string& startup_url)
|
||||
: BrowserWindow(delegate) {
|
||||
client_handler_ = new ClientHandlerStd(this, startup_url);
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::CreateBrowser(
|
||||
ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
CefWindowInfo window_info;
|
||||
window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect);
|
||||
|
||||
CefBrowserHost::CreateBrowser(window_info, client_handler_,
|
||||
client_handler_->startup_url(),
|
||||
settings, request_context);
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
// Note: This method may be called on any thread.
|
||||
// The window will be properly sized after the browser is created.
|
||||
windowInfo.SetAsChild(temp_handle, CefRect());
|
||||
client = client_handler_;
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::ShowPopup(ClientWindowHandle parent_handle,
|
||||
int x, int y, size_t width, size_t height) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_) {
|
||||
::Window parent_xwindow = GetXWindowForWidget(parent_handle);
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
|
||||
XReparentWindow(xdisplay, xwindow, parent_xwindow, x, y);
|
||||
|
||||
SetXWindowBounds(xwindow, x, y, width, height);
|
||||
SetXWindowVisible(xwindow, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::Show() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowVisible(xwindow, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::Hide() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowVisible(xwindow, false);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowBounds(xwindow, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::SetFocus(bool focus) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_)
|
||||
browser_->GetHost()->SetFocus(focus);
|
||||
}
|
||||
|
||||
ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// There is no GtkWidget* representation of this object.
|
||||
NOTREACHED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_STD_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_STD_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/browser_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents a native child window hosting a single windowed browser instance.
|
||||
// The methods of this class must be called on the main thread unless otherwise
|
||||
// indicated.
|
||||
class BrowserWindowStdGtk : public BrowserWindow {
|
||||
public:
|
||||
// Constructor may be called on any thread.
|
||||
// |delegate| must outlive this object.
|
||||
BrowserWindowStdGtk(Delegate* delegate,
|
||||
const std::string& startup_url);
|
||||
|
||||
// BrowserWindow methods.
|
||||
void CreateBrowser(ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) OVERRIDE;
|
||||
void GetPopupConfig(CefWindowHandle temp_handle,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) OVERRIDE;
|
||||
void ShowPopup(ClientWindowHandle parent_handle,
|
||||
int x, int y, size_t width, size_t height) OVERRIDE;
|
||||
void Show() OVERRIDE;
|
||||
void Hide() OVERRIDE;
|
||||
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
|
||||
void SetFocus(bool focus) OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_STD_GTK_H_
|
||||
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2014 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 "cefclient/browser/bytes_write_handler.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
BytesWriteHandler::BytesWriteHandler(size_t grow)
|
||||
: grow_(grow),
|
||||
datasize_(grow),
|
||||
offset_(0) {
|
||||
DCHECK_GT(grow, 0U);
|
||||
data_ = malloc(grow);
|
||||
DCHECK(data_ != NULL);
|
||||
}
|
||||
|
||||
BytesWriteHandler::~BytesWriteHandler() {
|
||||
if (data_)
|
||||
free(data_);
|
||||
}
|
||||
|
||||
size_t BytesWriteHandler::Write(const void* ptr, size_t size, size_t n) {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
size_t rv;
|
||||
if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
|
||||
Grow(size * n) == 0) {
|
||||
rv = 0;
|
||||
} else {
|
||||
memcpy(reinterpret_cast<char*>(data_) + offset_, ptr, size * n);
|
||||
offset_ += size * n;
|
||||
rv = n;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int BytesWriteHandler::Seek(int64 offset, int whence) {
|
||||
int rv = -1L;
|
||||
base::AutoLock lock_scope(lock_);
|
||||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
if (offset_ + offset > datasize_ || offset_ + offset < 0)
|
||||
break;
|
||||
offset_ += offset;
|
||||
rv = 0;
|
||||
break;
|
||||
case SEEK_END: {
|
||||
int64 offset_abs = std::abs(offset);
|
||||
if (offset_abs > datasize_)
|
||||
break;
|
||||
offset_ = datasize_ - offset_abs;
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
case SEEK_SET:
|
||||
if (offset > datasize_ || offset < 0)
|
||||
break;
|
||||
offset_ = offset;
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int64 BytesWriteHandler::Tell() {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
return offset_;
|
||||
}
|
||||
|
||||
int BytesWriteHandler::Flush() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t BytesWriteHandler::Grow(size_t size) {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
size_t rv;
|
||||
size_t s = (size > grow_ ? size : grow_);
|
||||
void* tmp = realloc(data_, datasize_ + s);
|
||||
DCHECK(tmp != NULL);
|
||||
if (tmp) {
|
||||
data_ = tmp;
|
||||
datasize_ += s;
|
||||
rv = datasize_;
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2014 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 CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_lock.h"
|
||||
#include "include/cef_stream.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class BytesWriteHandler : public CefWriteHandler {
|
||||
public:
|
||||
explicit BytesWriteHandler(size_t grow);
|
||||
~BytesWriteHandler();
|
||||
|
||||
size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE;
|
||||
int Seek(int64 offset, int whence) OVERRIDE;
|
||||
int64 Tell() OVERRIDE;
|
||||
int Flush() OVERRIDE;
|
||||
bool MayBlock() OVERRIDE { return false; }
|
||||
|
||||
void* GetData() { return data_; }
|
||||
int64 GetDataSize() { return offset_; }
|
||||
|
||||
private:
|
||||
size_t Grow(size_t size);
|
||||
|
||||
size_t grow_;
|
||||
void* data_;
|
||||
int64 datasize_;
|
||||
int64 offset_;
|
||||
|
||||
base::Lock lock_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(BytesWriteHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(BytesWriteHandler);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_
|
||||
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2013 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 "cefclient/browser/client_app_browser.h"
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/cef_cookie.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ClientAppBrowser::ClientAppBrowser() {
|
||||
}
|
||||
|
||||
void ClientAppBrowser::OnBeforeCommandLineProcessing(
|
||||
const CefString& process_type,
|
||||
CefRefPtr<CefCommandLine> command_line) {
|
||||
// Pass additional command-line flags to the browser process.
|
||||
if (process_type.empty()) {
|
||||
// Pass additional command-line flags when off-screen rendering is enabled.
|
||||
if (command_line->HasSwitch(switches::kOffScreenRenderingEnabled)) {
|
||||
// If the PDF extension is enabled then cc Surfaces must be disabled for
|
||||
// PDFs to render correctly.
|
||||
// See https://bitbucket.org/chromiumembedded/cef/issues/1689 for details.
|
||||
if (!command_line->HasSwitch("disable-extensions") &&
|
||||
!command_line->HasSwitch("disable-pdf-extension")) {
|
||||
command_line->AppendSwitch("disable-surfaces");
|
||||
}
|
||||
|
||||
// Use software rendering and compositing (disable GPU) for increased FPS
|
||||
// and decreased CPU usage. This will also disable WebGL so remove these
|
||||
// switches if you need that capability.
|
||||
// See https://bitbucket.org/chromiumembedded/cef/issues/1257 for details.
|
||||
if (!command_line->HasSwitch(switches::kEnableGPU)) {
|
||||
command_line->AppendSwitch("disable-gpu");
|
||||
command_line->AppendSwitch("disable-gpu-compositing");
|
||||
}
|
||||
|
||||
// Synchronize the frame rate between all processes. This results in
|
||||
// decreased CPU usage by avoiding the generation of extra frames that
|
||||
// would otherwise be discarded. The frame rate can be set at browser
|
||||
// creation time via CefBrowserSettings.windowless_frame_rate or changed
|
||||
// dynamically using CefBrowserHost::SetWindowlessFrameRate. In cefclient
|
||||
// it can be set via the command-line using `--off-screen-frame-rate=XX`.
|
||||
// See https://bitbucket.org/chromiumembedded/cef/issues/1368 for details.
|
||||
command_line->AppendSwitch("enable-begin-frame-scheduling");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAppBrowser::OnContextInitialized() {
|
||||
CreateDelegates(delegates_);
|
||||
|
||||
// Register cookieable schemes with the global cookie manager.
|
||||
CefRefPtr<CefCookieManager> manager =
|
||||
CefCookieManager::GetGlobalManager(NULL);
|
||||
DCHECK(manager.get());
|
||||
manager->SetSupportedSchemes(cookieable_schemes_, NULL);
|
||||
|
||||
print_handler_ = CreatePrintHandler();
|
||||
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnContextInitialized(this);
|
||||
}
|
||||
|
||||
void ClientAppBrowser::OnBeforeChildProcessLaunch(
|
||||
CefRefPtr<CefCommandLine> command_line) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnBeforeChildProcessLaunch(this, command_line);
|
||||
}
|
||||
|
||||
void ClientAppBrowser::OnRenderProcessThreadCreated(
|
||||
CefRefPtr<CefListValue> extra_info) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnRenderProcessThreadCreated(this, extra_info);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2013 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 CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_APP_BROWSER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_APP_BROWSER_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "cefclient/common/client_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client app implementation for the browser process.
|
||||
class ClientAppBrowser : public ClientApp,
|
||||
public CefBrowserProcessHandler {
|
||||
public:
|
||||
// Interface for browser delegates. All Delegates must be returned via
|
||||
// CreateDelegates. Do not perform work in the Delegate
|
||||
// constructor. See CefBrowserProcessHandler for documentation.
|
||||
class Delegate : public virtual CefBase {
|
||||
public:
|
||||
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {}
|
||||
|
||||
virtual void OnBeforeChildProcessLaunch(
|
||||
CefRefPtr<ClientAppBrowser> app,
|
||||
CefRefPtr<CefCommandLine> command_line) {}
|
||||
|
||||
virtual void OnRenderProcessThreadCreated(
|
||||
CefRefPtr<ClientAppBrowser> app,
|
||||
CefRefPtr<CefListValue> extra_info) {}
|
||||
};
|
||||
|
||||
typedef std::set<CefRefPtr<Delegate> > DelegateSet;
|
||||
|
||||
ClientAppBrowser();
|
||||
|
||||
private:
|
||||
// Creates all of the Delegate objects. Implemented by cefclient in
|
||||
// client_app_delegates_browser.cc
|
||||
static void CreateDelegates(DelegateSet& delegates);
|
||||
|
||||
// Create the Linux print handler. Implemented by cefclient in
|
||||
// client_app_delegates_browser.cc
|
||||
static CefRefPtr<CefPrintHandler> CreatePrintHandler();
|
||||
|
||||
// CefApp methods.
|
||||
void OnBeforeCommandLineProcessing(
|
||||
const CefString& process_type,
|
||||
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
|
||||
CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefBrowserProcessHandler methods.
|
||||
void OnContextInitialized() OVERRIDE;
|
||||
void OnBeforeChildProcessLaunch(
|
||||
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
|
||||
void OnRenderProcessThreadCreated(
|
||||
CefRefPtr<CefListValue> extra_info) OVERRIDE;
|
||||
CefRefPtr<CefPrintHandler> GetPrintHandler() OVERRIDE {
|
||||
return print_handler_;
|
||||
}
|
||||
|
||||
// Set of supported Delegates.
|
||||
DelegateSet delegates_;
|
||||
|
||||
CefRefPtr<CefPrintHandler> print_handler_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientAppBrowser);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientAppBrowser);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_APP_BROWSER_H_
|
||||
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2012 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 "cefclient/browser/client_app_browser.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "cefclient/browser/print_handler_gtk.h"
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
// static
|
||||
void ClientAppBrowser::CreateDelegates(DelegateSet& delegates) {
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefPrintHandler> ClientAppBrowser::CreatePrintHandler() {
|
||||
#if defined(OS_LINUX)
|
||||
return new ClientPrintHandlerGtk();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,770 @@
|
||||
// Copyright (c) 2013 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 "cefclient/browser/client_handler.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/cef_frame.h"
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/resource_util.h"
|
||||
#include "cefclient/browser/root_window_manager.h"
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#define NEWLINE "\r\n"
|
||||
#else
|
||||
#define NEWLINE "\n"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// Custom menu command Ids.
|
||||
enum client_menu_ids {
|
||||
CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST,
|
||||
CLIENT_ID_CLOSE_DEVTOOLS,
|
||||
CLIENT_ID_INSPECT_ELEMENT,
|
||||
CLIENT_ID_TESTMENU_SUBMENU,
|
||||
CLIENT_ID_TESTMENU_CHECKITEM,
|
||||
CLIENT_ID_TESTMENU_RADIOITEM1,
|
||||
CLIENT_ID_TESTMENU_RADIOITEM2,
|
||||
CLIENT_ID_TESTMENU_RADIOITEM3,
|
||||
};
|
||||
|
||||
// Musr match the value in client_renderer.cc.
|
||||
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
|
||||
|
||||
std::string GetTimeString(const CefTime& value) {
|
||||
if (value.GetTimeT() == 0)
|
||||
return "Unspecified";
|
||||
|
||||
static const char* kMonths[] = {
|
||||
"January", "February", "March", "April", "May", "June", "July", "August",
|
||||
"September", "October", "November", "December"
|
||||
};
|
||||
std::string month;
|
||||
if (value.month >= 1 && value.month <= 12)
|
||||
month = kMonths[value.month - 1];
|
||||
else
|
||||
month = "Invalid";
|
||||
|
||||
std::stringstream ss;
|
||||
ss << month << " " << value.day_of_month << ", " << value.year << " " <<
|
||||
std::setfill('0') << std::setw(2) << value.hour << ":" <<
|
||||
std::setfill('0') << std::setw(2) << value.minute << ":" <<
|
||||
std::setfill('0') << std::setw(2) << value.second;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GetBinaryString(CefRefPtr<CefBinaryValue> value) {
|
||||
if (!value.get())
|
||||
return " ";
|
||||
|
||||
// Retrieve the value.
|
||||
const size_t size = value->GetSize();
|
||||
std::string src;
|
||||
src.resize(size);
|
||||
value->GetData(const_cast<char*>(src.data()), size, 0);
|
||||
|
||||
// Encode the value.
|
||||
return CefBase64Encode(src.data(), src.size());
|
||||
}
|
||||
|
||||
// Load a data: URI containing the error message.
|
||||
void LoadErrorPage(CefRefPtr<CefFrame> frame,
|
||||
const std::string& failed_url,
|
||||
cef_errorcode_t error_code,
|
||||
const std::string& other_info) {
|
||||
std::stringstream ss;
|
||||
ss << "<html><head><title>Page failed to load</title></head>"
|
||||
"<body bgcolor=\"white\">"
|
||||
"<h3>Page failed to load.</h3>"
|
||||
"URL: <a href=\"" << failed_url << "\">"<< failed_url << "</a>"
|
||||
"<br/>Error: " << test_runner::GetErrorString(error_code) <<
|
||||
" (" << error_code << ")";
|
||||
|
||||
if (!other_info.empty())
|
||||
ss << "<br/>" << other_info;
|
||||
|
||||
ss << "</body></html>";
|
||||
frame->LoadURL(test_runner::GetDataURI(ss.str(), "text/html"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ClientHandler::ClientHandler(Delegate* delegate,
|
||||
bool is_osr,
|
||||
const std::string& startup_url)
|
||||
: is_osr_(is_osr),
|
||||
startup_url_(startup_url),
|
||||
delegate_(delegate),
|
||||
browser_count_(0),
|
||||
console_log_file_(MainContext::Get()->GetConsoleLogPath()),
|
||||
first_console_message_(true),
|
||||
focus_on_editable_field_(false) {
|
||||
DCHECK(!console_log_file_.empty());
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// Provide the GTK-based dialog implementation on Linux.
|
||||
dialog_handler_ = new ClientDialogHandlerGtk();
|
||||
#endif
|
||||
|
||||
resource_manager_ = new CefResourceManager();
|
||||
test_runner::SetupResourceManager(resource_manager_);
|
||||
|
||||
// Read command line settings.
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
mouse_cursor_change_disabled_ =
|
||||
command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
|
||||
}
|
||||
|
||||
void ClientHandler::DetachDelegate() {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&ClientHandler::DetachDelegate, this));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(delegate_);
|
||||
delegate_ = NULL;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnProcessMessageReceived(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (message_router_->OnProcessMessageReceived(browser, source_process,
|
||||
message)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for messages from the client renderer.
|
||||
std::string message_name = message->GetName();
|
||||
if (message_name == kFocusedNodeChangedMessage) {
|
||||
// A message is sent from ClientRenderDelegate to tell us whether the
|
||||
// currently focused DOM node is editable. Use of |focus_on_editable_field_|
|
||||
// is redundant with CefKeyEvent.focus_on_editable_field in OnPreKeyEvent
|
||||
// but is useful for demonstration purposes.
|
||||
focus_on_editable_field_ = message->GetArgumentList()->GetBool(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientHandler::OnBeforeContextMenu(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefContextMenuParams> params,
|
||||
CefRefPtr<CefMenuModel> model) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
|
||||
// Add a separator if the menu already has items.
|
||||
if (model->GetCount() > 0)
|
||||
model->AddSeparator();
|
||||
|
||||
// Add DevTools items to all context menus.
|
||||
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
|
||||
model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
|
||||
model->AddSeparator();
|
||||
model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
|
||||
|
||||
// Test context menu features.
|
||||
BuildTestMenu(model);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientHandler::OnContextMenuCommand(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefContextMenuParams> params,
|
||||
int command_id,
|
||||
EventFlags event_flags) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
switch (command_id) {
|
||||
case CLIENT_ID_SHOW_DEVTOOLS:
|
||||
ShowDevTools(browser, CefPoint());
|
||||
return true;
|
||||
case CLIENT_ID_CLOSE_DEVTOOLS:
|
||||
CloseDevTools(browser);
|
||||
return true;
|
||||
case CLIENT_ID_INSPECT_ELEMENT:
|
||||
ShowDevTools(browser, CefPoint(params->GetXCoord(), params->GetYCoord()));
|
||||
return true;
|
||||
default: // Allow default handling, if any.
|
||||
return ExecuteTestMenu(command_id);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& url) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Only update the address for the main (top-level) frame.
|
||||
if (frame->IsMain())
|
||||
NotifyAddress(url);
|
||||
}
|
||||
|
||||
void ClientHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& title) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyTitle(title);
|
||||
}
|
||||
|
||||
void ClientHandler::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
|
||||
bool fullscreen) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
bool ClientHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message,
|
||||
const CefString& source,
|
||||
int line) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
FILE* file = fopen(console_log_file_.c_str(), "a");
|
||||
if (file) {
|
||||
std::stringstream ss;
|
||||
ss << "Message: " << message.ToString() << NEWLINE <<
|
||||
"Source: " << source.ToString() << NEWLINE <<
|
||||
"Line: " << line << NEWLINE <<
|
||||
"-----------------------" << NEWLINE;
|
||||
fputs(ss.str().c_str(), file);
|
||||
fclose(file);
|
||||
|
||||
if (first_console_message_) {
|
||||
test_runner::Alert(
|
||||
browser, "Console messages written to \"" + console_log_file_ + "\"");
|
||||
first_console_message_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientHandler::OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
CefRefPtr<CefBeforeDownloadCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Continue the download and show the "Save As" dialog.
|
||||
callback->Continue(MainContext::Get()->GetDownloadPath(suggested_name), true);
|
||||
}
|
||||
|
||||
void ClientHandler::OnDownloadUpdated(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
CefRefPtr<CefDownloadItemCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (download_item->IsComplete()) {
|
||||
test_runner::Alert(
|
||||
browser,
|
||||
"File \"" + download_item->GetFullPath().ToString() +
|
||||
"\" downloaded successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientHandler::OnDragEnter(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> dragData,
|
||||
CefDragHandler::DragOperationsMask mask) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Forbid dragging of link URLs.
|
||||
if (mask & DRAG_OPERATION_LINK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientHandler::OnDraggableRegionsChanged(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const std::vector<CefDraggableRegion>& regions) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyDraggableRegions(regions);
|
||||
}
|
||||
|
||||
bool ClientHandler::OnRequestGeolocationPermission(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& requesting_url,
|
||||
int request_id,
|
||||
CefRefPtr<CefGeolocationCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Allow geolocation access from all websites.
|
||||
callback->Continue(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
|
||||
const CefKeyEvent& event,
|
||||
CefEventHandle os_event,
|
||||
bool* is_keyboard_shortcut) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!event.focus_on_editable_field && event.windows_key_code == 0x20) {
|
||||
// Special handling for the space character when an input element does not
|
||||
// have focus. Handling the event in OnPreKeyEvent() keeps the event from
|
||||
// being processed in the renderer. If we instead handled the event in the
|
||||
// OnKeyEvent() method the space key would cause the window to scroll in
|
||||
// addition to showing the alert box.
|
||||
if (event.type == KEYEVENT_RAWKEYDOWN)
|
||||
test_runner::Alert(browser, "You pressed the space bar!");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
// Return true to cancel the popup window.
|
||||
return !CreatePopupWindow(browser, false, popupFeatures, windowInfo, client,
|
||||
settings);
|
||||
}
|
||||
|
||||
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
browser_count_++;
|
||||
|
||||
if (!message_router_) {
|
||||
// Create the browser-side router for query handling.
|
||||
CefMessageRouterConfig config;
|
||||
message_router_ = CefMessageRouterBrowserSide::Create(config);
|
||||
|
||||
// Register handlers with the router.
|
||||
test_runner::CreateMessageHandlers(message_handler_set_);
|
||||
MessageHandlerSet::const_iterator it = message_handler_set_.begin();
|
||||
for (; it != message_handler_set_.end(); ++it)
|
||||
message_router_->AddHandler(*(it), false);
|
||||
}
|
||||
|
||||
// Disable mouse cursor change if requested via the command-line flag.
|
||||
if (mouse_cursor_change_disabled_)
|
||||
browser->GetHost()->SetMouseCursorChangeDisabled(true);
|
||||
|
||||
NotifyBrowserCreated(browser);
|
||||
}
|
||||
|
||||
bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyBrowserClosing(browser);
|
||||
|
||||
// Allow the close. For windowed browsers this will result in the OS close
|
||||
// event being sent.
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (--browser_count_ == 0) {
|
||||
// Remove and delete message router handlers.
|
||||
MessageHandlerSet::const_iterator it =
|
||||
message_handler_set_.begin();
|
||||
for (; it != message_handler_set_.end(); ++it) {
|
||||
message_router_->RemoveHandler(*(it));
|
||||
delete *(it);
|
||||
}
|
||||
message_handler_set_.clear();
|
||||
message_router_ = NULL;
|
||||
}
|
||||
|
||||
NotifyBrowserClosed(browser);
|
||||
}
|
||||
|
||||
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyLoadingState(isLoading, canGoBack, canGoForward);
|
||||
}
|
||||
|
||||
void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
ErrorCode errorCode,
|
||||
const CefString& errorText,
|
||||
const CefString& failedUrl) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Don't display an error for downloaded files.
|
||||
if (errorCode == ERR_ABORTED)
|
||||
return;
|
||||
|
||||
// Don't display an error for external protocols that we allow the OS to
|
||||
// handle. See OnProtocolExecution().
|
||||
if (errorCode == ERR_UNKNOWN_URL_SCHEME) {
|
||||
std::string urlStr = frame->GetURL();
|
||||
if (urlStr.find("spotify:") == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the error page.
|
||||
LoadErrorPage(frame, failedUrl, errorCode, errorText);
|
||||
}
|
||||
|
||||
bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
bool is_redirect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
message_router_->OnBeforeBrowse(browser, frame);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnOpenURLFromTab(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
CefRequestHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture) {
|
||||
if (user_gesture && target_disposition == WOD_NEW_BACKGROUND_TAB) {
|
||||
// Handle middle-click and ctrl + left-click by opening the URL in a new
|
||||
// browser window.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
true, is_osr(), CefRect(), target_url);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Open the URL in the current browser window.
|
||||
return false;
|
||||
}
|
||||
|
||||
cef_return_value_t ClientHandler::OnBeforeResourceLoad(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefRequestCallback> callback) {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
|
||||
callback);
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
return resource_manager_->GetResourceHandler(browser, frame, request);
|
||||
}
|
||||
|
||||
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
int64 new_size,
|
||||
CefRefPtr<CefRequestCallback> callback) {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
static const int64 max_size = 1024 * 1024 * 20; // 20mb.
|
||||
|
||||
// Grant the quota request if the size is reasonable.
|
||||
callback->Continue(new_size <= max_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientHandler::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
bool& allow_os_execution) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
std::string urlStr = url;
|
||||
|
||||
// Allow OS execution of Spotify URIs.
|
||||
if (urlStr.find("spotify:") == 0)
|
||||
allow_os_execution = true;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnCertificateError(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
ErrorCode cert_error,
|
||||
const CefString& request_url,
|
||||
CefRefPtr<CefSSLInfo> ssl_info,
|
||||
CefRefPtr<CefRequestCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
CefRefPtr<CefSSLCertPrincipal> subject = ssl_info->GetSubject();
|
||||
CefRefPtr<CefSSLCertPrincipal> issuer = ssl_info->GetIssuer();
|
||||
|
||||
// Build a table showing certificate information.
|
||||
std::stringstream ss;
|
||||
ss << "X.509 Certificate Information:"
|
||||
"<table border=1><tr><th>Field</th><th>Value</th></tr>" <<
|
||||
"<tr><td>Subject</td><td>" <<
|
||||
(subject.get() ? subject->GetDisplayName().ToString() : " ") <<
|
||||
"</td></tr>"
|
||||
"<tr><td>Issuer</td><td>" <<
|
||||
(issuer.get() ? issuer->GetDisplayName().ToString() : " ") <<
|
||||
"</td></tr>"
|
||||
"<tr><td>Serial #*</td><td>" <<
|
||||
GetBinaryString(ssl_info->GetSerialNumber()) << "</td></tr>"
|
||||
"<tr><td>Valid Start</td><td>" <<
|
||||
GetTimeString(ssl_info->GetValidStart()) << "</td></tr>"
|
||||
"<tr><td>Valid Expiry</td><td>" <<
|
||||
GetTimeString(ssl_info->GetValidExpiry()) << "</td></tr>"
|
||||
"<tr><td>DER Encoded*</td>"
|
||||
"<td style=\"max-width:800px;overflow:scroll;\">" <<
|
||||
GetBinaryString(ssl_info->GetDEREncoded()) << "</td></tr>"
|
||||
"<tr><td>PEM Encoded*</td>"
|
||||
"<td style=\"max-width:800px;overflow:scroll;\">" <<
|
||||
GetBinaryString(ssl_info->GetPEMEncoded()) << "</td></tr>"
|
||||
"</table> * Displayed value is base64 encoded.";
|
||||
|
||||
// Load the error page.
|
||||
LoadErrorPage(browser->GetMainFrame(), request_url, cert_error, ss.str());
|
||||
|
||||
return false; // Cancel the request.
|
||||
}
|
||||
|
||||
void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
message_router_->OnRenderProcessTerminated(browser);
|
||||
|
||||
// Don't reload if there's no start URL, or if the crash URL was specified.
|
||||
if (startup_url_.empty() || startup_url_ == "chrome://crash")
|
||||
return;
|
||||
|
||||
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
|
||||
std::string url = frame->GetURL();
|
||||
|
||||
// Don't reload if the termination occurred before any URL had successfully
|
||||
// loaded.
|
||||
if (url.empty())
|
||||
return;
|
||||
|
||||
std::string start_url = startup_url_;
|
||||
|
||||
// Convert URLs to lowercase for easier comparison.
|
||||
std::transform(url.begin(), url.end(), url.begin(), tolower);
|
||||
std::transform(start_url.begin(), start_url.end(), start_url.begin(),
|
||||
tolower);
|
||||
|
||||
// Don't reload the URL that just resulted in termination.
|
||||
if (url.find(start_url) == 0)
|
||||
return;
|
||||
|
||||
frame->LoadURL(startup_url_);
|
||||
}
|
||||
|
||||
int ClientHandler::GetBrowserCount() const {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
return browser_count_;
|
||||
}
|
||||
|
||||
void ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
|
||||
const CefPoint& inspect_element_at) {
|
||||
CefWindowInfo windowInfo;
|
||||
CefRefPtr<CefClient> client;
|
||||
CefBrowserSettings settings;
|
||||
|
||||
if (CreatePopupWindow(browser, true, CefPopupFeatures(), windowInfo, client,
|
||||
settings)) {
|
||||
browser->GetHost()->ShowDevTools(windowInfo, client, settings,
|
||||
inspect_element_at);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
|
||||
browser->GetHost()->CloseDevTools();
|
||||
}
|
||||
|
||||
|
||||
bool ClientHandler::CreatePopupWindow(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
bool is_devtools,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
// Note: This method will be called on multiple threads.
|
||||
|
||||
// The popup browser will be parented to a new native window.
|
||||
// Don't show URL bar and navigation buttons on DevTools windows.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
|
||||
!is_devtools, is_osr(), popupFeatures, windowInfo, client, settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ClientHandler::NotifyBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyBrowserCreated, this, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnBrowserCreated(browser);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyBrowserClosing(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyBrowserClosing, this, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnBrowserClosing(browser);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyBrowserClosed(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyBrowserClosed, this, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnBrowserClosed(browser);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyAddress(const CefString& url) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyAddress, this, url));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnSetAddress(url);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyTitle(const CefString& title) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyTitle, this, title));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnSetTitle(title);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyFullscreen(bool fullscreen) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyFullscreen, this, fullscreen));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnSetFullscreen(fullscreen);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyLoadingState, this,
|
||||
isLoading, canGoBack, canGoForward));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyDraggableRegions, this, regions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnSetDraggableRegions(regions);
|
||||
}
|
||||
|
||||
void ClientHandler::BuildTestMenu(CefRefPtr<CefMenuModel> model) {
|
||||
if (model->GetCount() > 0)
|
||||
model->AddSeparator();
|
||||
|
||||
// Build the sub menu.
|
||||
CefRefPtr<CefMenuModel> submenu =
|
||||
model->AddSubMenu(CLIENT_ID_TESTMENU_SUBMENU, "Context Menu Test");
|
||||
submenu->AddCheckItem(CLIENT_ID_TESTMENU_CHECKITEM, "Check Item");
|
||||
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM1, "Radio Item 1", 0);
|
||||
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM2, "Radio Item 2", 0);
|
||||
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM3, "Radio Item 3", 0);
|
||||
|
||||
// Check the check item.
|
||||
if (test_menu_state_.check_item)
|
||||
submenu->SetChecked(CLIENT_ID_TESTMENU_CHECKITEM, true);
|
||||
|
||||
// Check the selected radio item.
|
||||
submenu->SetChecked(
|
||||
CLIENT_ID_TESTMENU_RADIOITEM1 + test_menu_state_.radio_item, true);
|
||||
}
|
||||
|
||||
bool ClientHandler::ExecuteTestMenu(int command_id) {
|
||||
if (command_id == CLIENT_ID_TESTMENU_CHECKITEM) {
|
||||
// Toggle the check item.
|
||||
test_menu_state_.check_item ^= 1;
|
||||
return true;
|
||||
} else if (command_id >= CLIENT_ID_TESTMENU_RADIOITEM1 &&
|
||||
command_id <= CLIENT_ID_TESTMENU_RADIOITEM3) {
|
||||
// Store the selected radio item.
|
||||
test_menu_state_.radio_item = (command_id - CLIENT_ID_TESTMENU_RADIOITEM1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow default handling to proceed.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,352 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "include/cef_client.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "include/wrapper/cef_message_router.h"
|
||||
#include "include/wrapper/cef_resource_manager.h"
|
||||
#include "cefclient/browser/client_types.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "cefclient/browser/dialog_handler_gtk.h"
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client handler abstract base class. Provides common functionality shared by
|
||||
// all concrete client handler implementations.
|
||||
class ClientHandler : public CefClient,
|
||||
public CefContextMenuHandler,
|
||||
public CefDisplayHandler,
|
||||
public CefDownloadHandler,
|
||||
public CefDragHandler,
|
||||
public CefGeolocationHandler,
|
||||
public CefKeyboardHandler,
|
||||
public CefLifeSpanHandler,
|
||||
public CefLoadHandler,
|
||||
public CefRequestHandler {
|
||||
public:
|
||||
// Implement this interface to receive notification of ClientHandler
|
||||
// events. The methods of this class will be called on the main thread.
|
||||
class Delegate {
|
||||
public:
|
||||
// Called when the browser is created.
|
||||
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Called when the browser is closing.
|
||||
virtual void OnBrowserClosing(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Called when the browser has been closed.
|
||||
virtual void OnBrowserClosed(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Set the window URL address.
|
||||
virtual void OnSetAddress(const std::string& url) = 0;
|
||||
|
||||
// Set the window title.
|
||||
virtual void OnSetTitle(const std::string& title) = 0;
|
||||
|
||||
// Set fullscreen mode.
|
||||
virtual void OnSetFullscreen(bool fullscreen) = 0;
|
||||
|
||||
// Set the loading state.
|
||||
virtual void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) = 0;
|
||||
|
||||
// Set the draggable regions.
|
||||
virtual void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
|
||||
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
|
||||
|
||||
// Constructor may be called on any thread.
|
||||
// |delegate| must outlive this object or DetachDelegate() must be called.
|
||||
ClientHandler(Delegate* delegate,
|
||||
bool is_osr,
|
||||
const std::string& startup_url);
|
||||
|
||||
// This object may outlive the Delegate object so it's necessary for the
|
||||
// Delegate to detach itself before destruction.
|
||||
void DetachDelegate();
|
||||
|
||||
// CefClient methods
|
||||
CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefDragHandler> GetDragHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) OVERRIDE;
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
CefRefPtr<CefDialogHandler> GetDialogHandler() OVERRIDE {
|
||||
return dialog_handler_;
|
||||
}
|
||||
CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() OVERRIDE {
|
||||
return dialog_handler_;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CefContextMenuHandler methods
|
||||
void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefContextMenuParams> params,
|
||||
CefRefPtr<CefMenuModel> model) OVERRIDE;
|
||||
bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefContextMenuParams> params,
|
||||
int command_id,
|
||||
EventFlags event_flags) OVERRIDE;
|
||||
|
||||
// CefDisplayHandler methods
|
||||
void OnAddressChange(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& url) OVERRIDE;
|
||||
void OnTitleChange(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& title) OVERRIDE;
|
||||
void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
|
||||
bool fullscreen) OVERRIDE;
|
||||
bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message,
|
||||
const CefString& source,
|
||||
int line) OVERRIDE;
|
||||
|
||||
// CefDownloadHandler methods
|
||||
void OnBeforeDownload(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
const CefString& suggested_name,
|
||||
CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE;
|
||||
void OnDownloadUpdated(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDownloadItem> download_item,
|
||||
CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE;
|
||||
|
||||
// CefDragHandler methods
|
||||
bool OnDragEnter(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> dragData,
|
||||
CefDragHandler::DragOperationsMask mask) OVERRIDE;
|
||||
|
||||
void OnDraggableRegionsChanged(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
|
||||
// CefGeolocationHandler methods
|
||||
bool OnRequestGeolocationPermission(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& requesting_url,
|
||||
int request_id,
|
||||
CefRefPtr<CefGeolocationCallback> callback) OVERRIDE;
|
||||
|
||||
// CefKeyboardHandler methods
|
||||
bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
|
||||
const CefKeyEvent& event,
|
||||
CefEventHandle os_event,
|
||||
bool* is_keyboard_shortcut) OVERRIDE;
|
||||
|
||||
// CefLifeSpanHandler methods
|
||||
bool OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) OVERRIDE;
|
||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
||||
// CefLoadHandler methods
|
||||
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
void OnLoadError(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
ErrorCode errorCode,
|
||||
const CefString& errorText,
|
||||
const CefString& failedUrl) OVERRIDE;
|
||||
|
||||
// CefRequestHandler methods
|
||||
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
bool is_redirect) OVERRIDE;
|
||||
bool OnOpenURLFromTab(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
CefRequestHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture) OVERRIDE;
|
||||
cef_return_value_t OnBeforeResourceLoad(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) OVERRIDE;
|
||||
bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
int64 new_size,
|
||||
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
|
||||
void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& url,
|
||||
bool& allow_os_execution) OVERRIDE;
|
||||
bool OnCertificateError(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
ErrorCode cert_error,
|
||||
const CefString& request_url,
|
||||
CefRefPtr<CefSSLInfo> ssl_info,
|
||||
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
|
||||
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) OVERRIDE;
|
||||
|
||||
// Returns the number of browsers currently using this handler. Can only be
|
||||
// called on the CEF UI thread.
|
||||
int GetBrowserCount() const;
|
||||
|
||||
// Show a new DevTools popup window.
|
||||
void ShowDevTools(CefRefPtr<CefBrowser> browser,
|
||||
const CefPoint& inspect_element_at);
|
||||
|
||||
// Close the existing DevTools popup window, if any.
|
||||
void CloseDevTools(CefRefPtr<CefBrowser> browser);
|
||||
|
||||
// Returns the startup URL.
|
||||
std::string startup_url() const { return startup_url_; }
|
||||
|
||||
// Returns true if this handler uses off-screen rendering.
|
||||
bool is_osr() const { return is_osr_; }
|
||||
|
||||
private:
|
||||
// Create a new popup window using the specified information. |is_devtools|
|
||||
// will be true if the window will be used for DevTools. Return true to
|
||||
// proceed with popup browser creation or false to cancel the popup browser.
|
||||
// May be called on any thead.
|
||||
bool CreatePopupWindow(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
bool is_devtools,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings);
|
||||
|
||||
// Execute Delegate notifications on the main thread.
|
||||
void NotifyBrowserCreated(CefRefPtr<CefBrowser> browser);
|
||||
void NotifyBrowserClosing(CefRefPtr<CefBrowser> browser);
|
||||
void NotifyBrowserClosed(CefRefPtr<CefBrowser> browser);
|
||||
void NotifyAddress(const CefString& url);
|
||||
void NotifyTitle(const CefString& title);
|
||||
void NotifyFullscreen(bool fullscreen);
|
||||
void NotifyLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward);
|
||||
void NotifyDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions);
|
||||
|
||||
// Test context menu creation.
|
||||
void BuildTestMenu(CefRefPtr<CefMenuModel> model);
|
||||
bool ExecuteTestMenu(int command_id);
|
||||
|
||||
// THREAD SAFE MEMBERS
|
||||
// The following members may be accessed from any thread.
|
||||
|
||||
// True if this handler uses off-screen rendering.
|
||||
const bool is_osr_;
|
||||
|
||||
// The startup URL.
|
||||
const std::string startup_url_;
|
||||
|
||||
// True if mouse cursor change is disabled.
|
||||
bool mouse_cursor_change_disabled_;
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// Custom dialog handler for GTK.
|
||||
CefRefPtr<ClientDialogHandlerGtk> dialog_handler_;
|
||||
#endif
|
||||
|
||||
// Handles the browser side of query routing. The renderer side is handled
|
||||
// in client_renderer.cc.
|
||||
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
|
||||
|
||||
// Manages the registration and delivery of resources.
|
||||
CefRefPtr<CefResourceManager> resource_manager_;
|
||||
|
||||
// MAIN THREAD MEMBERS
|
||||
// The following members will only be accessed on the main thread. This will
|
||||
// be the same as the CEF UI thread except when using multi-threaded message
|
||||
// loop mode on Windows.
|
||||
|
||||
Delegate* delegate_;
|
||||
|
||||
// UI THREAD MEMBERS
|
||||
// The following members will only be accessed on the CEF UI thread.
|
||||
|
||||
// Track state information for the text context menu.
|
||||
struct TestMenuState {
|
||||
TestMenuState() : check_item(true), radio_item(0) {}
|
||||
bool check_item;
|
||||
int radio_item;
|
||||
} test_menu_state_;
|
||||
|
||||
// The current number of browsers using this handler.
|
||||
int browser_count_;
|
||||
|
||||
// Console logging state.
|
||||
const std::string console_log_file_;
|
||||
bool first_console_message_;
|
||||
|
||||
// True if an editable field currently has focus.
|
||||
bool focus_on_editable_field_;
|
||||
|
||||
// Set of Handlers registered with the message router.
|
||||
MessageHandlerSet message_handler_set_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientHandler);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_H_
|
||||
@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/client_handler_osr.h"
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ClientHandlerOsr::ClientHandlerOsr(Delegate* delegate,
|
||||
OsrDelegate* osr_delegate,
|
||||
const std::string& startup_url)
|
||||
: ClientHandler(delegate, true, startup_url),
|
||||
osr_delegate_(osr_delegate) {
|
||||
DCHECK(osr_delegate_);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::DetachOsrDelegate() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&ClientHandlerOsr::DetachOsrDelegate, this));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(osr_delegate_);
|
||||
osr_delegate_ = NULL;
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (osr_delegate_)
|
||||
osr_delegate_->OnAfterCreated(browser);
|
||||
ClientHandler::OnAfterCreated(browser);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (osr_delegate_)
|
||||
osr_delegate_->OnBeforeClose(browser);
|
||||
ClientHandler::OnBeforeClose(browser);
|
||||
}
|
||||
|
||||
bool ClientHandlerOsr::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return false;
|
||||
return osr_delegate_->GetRootScreenRect(browser, rect);
|
||||
}
|
||||
|
||||
bool ClientHandlerOsr::GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return false;
|
||||
return osr_delegate_->GetViewRect(browser, rect);
|
||||
}
|
||||
|
||||
bool ClientHandlerOsr::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return false;
|
||||
return osr_delegate_->GetScreenPoint(browser, viewX, viewY, screenX, screenY);
|
||||
}
|
||||
|
||||
bool ClientHandlerOsr::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefScreenInfo& screen_info) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return false;
|
||||
return osr_delegate_->GetScreenInfo(browser, screen_info);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return;
|
||||
return osr_delegate_->OnPopupShow(browser, show);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return;
|
||||
return osr_delegate_->OnPopupSize(browser, rect);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
PaintElementType type,
|
||||
const RectList& dirtyRects,
|
||||
const void* buffer,
|
||||
int width,
|
||||
int height) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return;
|
||||
osr_delegate_->OnPaint(browser, type, dirtyRects, buffer, width, height);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::OnCursorChange(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor,
|
||||
CursorType type,
|
||||
const CefCursorInfo& custom_cursor_info) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return;
|
||||
osr_delegate_->OnCursorChange(browser, cursor, type, custom_cursor_info);
|
||||
}
|
||||
|
||||
bool ClientHandlerOsr::StartDragging(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> drag_data,
|
||||
CefRenderHandler::DragOperationsMask allowed_ops,
|
||||
int x, int y) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return false;
|
||||
return osr_delegate_->StartDragging(browser, drag_data, allowed_ops, x, y);
|
||||
}
|
||||
|
||||
void ClientHandlerOsr::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::DragOperation operation) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!osr_delegate_)
|
||||
return;
|
||||
osr_delegate_->UpdateDragCursor(browser, operation);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_OSR_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_OSR_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/client_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client handler implementation for windowless browsers. There will only ever
|
||||
// be one browser per handler instance.
|
||||
class ClientHandlerOsr : public ClientHandler,
|
||||
public CefRenderHandler {
|
||||
public:
|
||||
// Implement this interface to receive notification of ClientHandlerOsr
|
||||
// events. The methods of this class will be called on the CEF UI thread.
|
||||
class OsrDelegate {
|
||||
public:
|
||||
// These methods match the CefLifeSpanHandler interface.
|
||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) = 0;
|
||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// These methods match the CefRenderHandler interface.
|
||||
virtual bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) = 0;
|
||||
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) = 0;
|
||||
virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) = 0;
|
||||
virtual bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefScreenInfo& screen_info) = 0;
|
||||
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) = 0;
|
||||
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) = 0;
|
||||
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
PaintElementType type,
|
||||
const RectList& dirtyRects,
|
||||
const void* buffer,
|
||||
int width,
|
||||
int height) = 0;
|
||||
virtual void OnCursorChange(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor,
|
||||
CefRenderHandler::CursorType type,
|
||||
const CefCursorInfo& custom_cursor_info) = 0;
|
||||
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> drag_data,
|
||||
CefRenderHandler::DragOperationsMask allowed_ops,
|
||||
int x, int y) = 0;
|
||||
virtual void UpdateDragCursor(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::DragOperation operation) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~OsrDelegate() {}
|
||||
};
|
||||
|
||||
ClientHandlerOsr(Delegate* delegate,
|
||||
OsrDelegate* osr_delegate,
|
||||
const std::string& startup_url);
|
||||
|
||||
// This object may outlive the OsrDelegate object so it's necessary for the
|
||||
// OsrDelegate to detach itself before destruction.
|
||||
void DetachOsrDelegate();
|
||||
|
||||
// CefClient methods.
|
||||
CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefLifeSpanHandler methods.
|
||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
||||
// CefRenderHandler methods.
|
||||
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE;
|
||||
bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE;
|
||||
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) OVERRIDE;
|
||||
bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefScreenInfo& screen_info) OVERRIDE;
|
||||
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
|
||||
void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) OVERRIDE;
|
||||
void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer,
|
||||
int width,
|
||||
int height) OVERRIDE;
|
||||
void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor,
|
||||
CursorType type,
|
||||
const CefCursorInfo& custom_cursor_info) OVERRIDE;
|
||||
bool StartDragging(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> drag_data,
|
||||
CefRenderHandler::DragOperationsMask allowed_ops,
|
||||
int x, int y) OVERRIDE;
|
||||
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::DragOperation operation) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Only accessed on the UI thread.
|
||||
OsrDelegate* osr_delegate_;
|
||||
|
||||
// Include the default reference counting implementation.
|
||||
IMPLEMENT_REFCOUNTING(ClientHandlerOsr);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientHandlerOsr);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_OSR_H_
|
||||
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/client_handler_std.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ClientHandlerStd::ClientHandlerStd(Delegate* delegate,
|
||||
const std::string& startup_url)
|
||||
: ClientHandler(delegate, false, startup_url) {
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_STD_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_STD_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/client_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client handler implementation for windowed browsers. There will only ever be
|
||||
// one browser per handler instance.
|
||||
class ClientHandlerStd : public ClientHandler {
|
||||
public:
|
||||
ClientHandlerStd(Delegate* delegate,
|
||||
const std::string& startup_url);
|
||||
|
||||
private:
|
||||
// Include the default reference counting implementation.
|
||||
IMPLEMENT_REFCOUNTING(ClientHandlerStd);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientHandlerStd);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_STD_H_
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_base.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
// The Linux client uses GTK instead of the underlying platform type (X11).
|
||||
#define ClientWindowHandle GtkWidget*
|
||||
#else
|
||||
#define ClientWindowHandle CefWindowHandle
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Forward declaration of ObjC types used by cefclient and not provided by
|
||||
// include/internal/cef_types_mac.h.
|
||||
#ifdef __cplusplus
|
||||
#ifdef __OBJC__
|
||||
@class NSWindow;
|
||||
#else
|
||||
class NSWindow;
|
||||
#endif
|
||||
#endif
|
||||
#endif // defined OS_MACOSX
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_
|
||||
|
||||
@ -0,0 +1,431 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/dialog_handler_gtk.h"
|
||||
|
||||
#include <libgen.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "cefclient/browser/root_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kPromptTextId[] = "cef_prompt_text";
|
||||
|
||||
// If there's a text entry in the dialog, get the text from the first one and
|
||||
// return it.
|
||||
std::string GetPromptText(GtkDialog* dialog) {
|
||||
GtkWidget* widget = static_cast<GtkWidget*>(
|
||||
g_object_get_data(G_OBJECT(dialog), kPromptTextId));
|
||||
if (widget)
|
||||
return gtk_entry_get_text(GTK_ENTRY(widget));
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string GetDescriptionFromMimeType(const std::string& mime_type) {
|
||||
// Check for wild card mime types and return an appropriate description.
|
||||
static const struct {
|
||||
const char* mime_type;
|
||||
const char* label;
|
||||
} kWildCardMimeTypes[] = {
|
||||
{ "audio", "Audio Files" },
|
||||
{ "image", "Image Files" },
|
||||
{ "text", "Text Files" },
|
||||
{ "video", "Video Files" },
|
||||
};
|
||||
|
||||
for (size_t i = 0;
|
||||
i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) {
|
||||
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
|
||||
return std::string(kWildCardMimeTypes[i].label);
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void AddFilters(GtkFileChooser* chooser,
|
||||
const std::vector<CefString>& accept_filters,
|
||||
bool include_all_files,
|
||||
std::vector<GtkFileFilter*>* filters) {
|
||||
bool has_filter = false;
|
||||
|
||||
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||
const std::string& filter = accept_filters[i];
|
||||
if (filter.empty())
|
||||
continue;
|
||||
|
||||
std::vector<std::string> extensions;
|
||||
std::string description;
|
||||
|
||||
size_t sep_index = filter.find('|');
|
||||
if (sep_index != std::string::npos) {
|
||||
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||
description = filter.substr(0, sep_index);
|
||||
|
||||
const std::string& exts = filter.substr(sep_index + 1);
|
||||
size_t last = 0;
|
||||
size_t size = exts.size();
|
||||
for (size_t i = 0; i <= size; ++i) {
|
||||
if (i == size || exts[i] == ';') {
|
||||
std::string ext(exts, last, i - last);
|
||||
if (!ext.empty() && ext[0] == '.')
|
||||
extensions.push_back(ext);
|
||||
last = i + 1;
|
||||
}
|
||||
}
|
||||
} else if (filter[0] == '.') {
|
||||
// Treat as an extension beginning with the '.' character.
|
||||
extensions.push_back(filter);
|
||||
} else {
|
||||
// Otherwise convert mime type to one or more extensions.
|
||||
description = GetDescriptionFromMimeType(filter);
|
||||
|
||||
std::vector<CefString> ext;
|
||||
CefGetExtensionsForMimeType(filter, ext);
|
||||
for (size_t x = 0; x < ext.size(); ++x)
|
||||
extensions.push_back("." + ext[x].ToString());
|
||||
}
|
||||
|
||||
if (extensions.empty())
|
||||
continue;
|
||||
|
||||
GtkFileFilter* gtk_filter = gtk_file_filter_new();
|
||||
|
||||
std::string ext_str;
|
||||
for (size_t x = 0; x < extensions.size(); ++x) {
|
||||
const std::string& pattern = "*" + extensions[x];
|
||||
if (x != 0)
|
||||
ext_str += ";";
|
||||
ext_str += pattern;
|
||||
gtk_file_filter_add_pattern(gtk_filter, pattern.c_str());
|
||||
}
|
||||
|
||||
if (description.empty())
|
||||
description = ext_str;
|
||||
else
|
||||
description += " (" + ext_str + ")";
|
||||
|
||||
gtk_file_filter_set_name(gtk_filter, description.c_str());
|
||||
gtk_file_chooser_add_filter(chooser, gtk_filter);
|
||||
if (!has_filter)
|
||||
has_filter = true;
|
||||
|
||||
filters->push_back(gtk_filter);
|
||||
}
|
||||
|
||||
// Add the *.* filter, but only if we have added other filters (otherwise it
|
||||
// is implied).
|
||||
if (include_all_files && has_filter) {
|
||||
GtkFileFilter* filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_filter_set_name(filter, "All Files (*)");
|
||||
gtk_file_chooser_add_filter(chooser, filter);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||
if (root_window.get())
|
||||
return root_window->GetWindowHandle();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
ClientDialogHandlerGtk::ClientDialogHandlerGtk()
|
||||
: gtk_dialog_(NULL) {
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
FileDialogMode mode,
|
||||
const CefString& title,
|
||||
const CefString& default_file_path,
|
||||
const std::vector<CefString>& accept_filters,
|
||||
int selected_accept_filter,
|
||||
CefRefPtr<CefFileDialogCallback> callback) {
|
||||
std::vector<CefString> files;
|
||||
|
||||
GtkFileChooserAction action;
|
||||
const gchar* accept_button;
|
||||
|
||||
// Remove any modifier flags.
|
||||
FileDialogMode mode_type =
|
||||
static_cast<FileDialogMode>(mode & FILE_DIALOG_TYPE_MASK);
|
||||
|
||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||
accept_button = GTK_STOCK_OPEN;
|
||||
} else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
|
||||
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||
accept_button = GTK_STOCK_OPEN;
|
||||
} else if (mode_type == FILE_DIALOG_SAVE) {
|
||||
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||
accept_button = GTK_STOCK_SAVE;
|
||||
} else {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string title_str;
|
||||
if (!title.empty()) {
|
||||
title_str = title;
|
||||
} else {
|
||||
switch (mode_type) {
|
||||
case FILE_DIALOG_OPEN:
|
||||
title_str = "Open File";
|
||||
break;
|
||||
case FILE_DIALOG_OPEN_MULTIPLE:
|
||||
title_str = "Open Files";
|
||||
break;
|
||||
case FILE_DIALOG_OPEN_FOLDER:
|
||||
title_str = "Open Folder";
|
||||
break;
|
||||
case FILE_DIALOG_SAVE:
|
||||
title_str = "Save File";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* window = GetWindow(browser);
|
||||
DCHECK(window);
|
||||
|
||||
GtkWidget* dialog = gtk_file_chooser_dialog_new(
|
||||
title_str.c_str(),
|
||||
GTK_WINDOW(window),
|
||||
action,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
accept_button, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
if (mode_type == FILE_DIALOG_SAVE) {
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(
|
||||
GTK_FILE_CHOOSER(dialog),
|
||||
!!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
||||
}
|
||||
|
||||
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
||||
!(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
||||
|
||||
if (!default_file_path.empty()) {
|
||||
const std::string& file_path = default_file_path;
|
||||
bool exists = false;
|
||||
|
||||
if (mode_type == FILE_DIALOG_SAVE) {
|
||||
struct stat sb;
|
||||
if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) {
|
||||
// Use the directory and name of the existing file.
|
||||
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
|
||||
file_path.data());
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
// Set the current file name but let the user choose the directory.
|
||||
std::string file_name_str = file_path;
|
||||
const char* file_name = basename(const_cast<char*>(file_name_str.data()));
|
||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), file_name);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<GtkFileFilter*> filters;
|
||||
AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters);
|
||||
if (selected_accept_filter < static_cast<int>(filters.size())) {
|
||||
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
|
||||
filters[selected_accept_filter]);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER ||
|
||||
mode_type == FILE_DIALOG_SAVE) {
|
||||
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
files.push_back(std::string(filename));
|
||||
success = true;
|
||||
} else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||
GSList* filenames =
|
||||
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
||||
if (filenames) {
|
||||
for (GSList* iter = filenames; iter != NULL;
|
||||
iter = g_slist_next(iter)) {
|
||||
std::string path(static_cast<char*>(iter->data));
|
||||
g_free(iter->data);
|
||||
files.push_back(path);
|
||||
}
|
||||
g_slist_free(filenames);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int filter_index = selected_accept_filter;
|
||||
if (success) {
|
||||
GtkFileFilter* selected_filter =
|
||||
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
|
||||
if (selected_filter != NULL) {
|
||||
for (size_t x = 0; x < filters.size(); ++x) {
|
||||
if (filters[x] == selected_filter) {
|
||||
filter_index = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
if (success)
|
||||
callback->Continue(filter_index, files);
|
||||
else
|
||||
callback->Cancel();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnJSDialog(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
const CefString& accept_lang,
|
||||
JSDialogType dialog_type,
|
||||
const CefString& message_text,
|
||||
const CefString& default_prompt_text,
|
||||
CefRefPtr<CefJSDialogCallback> callback,
|
||||
bool& suppress_message) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
GtkButtonsType buttons = GTK_BUTTONS_NONE;
|
||||
GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER;
|
||||
std::string title;
|
||||
|
||||
switch (dialog_type) {
|
||||
case JSDIALOGTYPE_ALERT:
|
||||
buttons = GTK_BUTTONS_NONE;
|
||||
gtk_message_type = GTK_MESSAGE_WARNING;
|
||||
title = "JavaScript Alert";
|
||||
break;
|
||||
|
||||
case JSDIALOGTYPE_CONFIRM:
|
||||
buttons = GTK_BUTTONS_CANCEL;
|
||||
gtk_message_type = GTK_MESSAGE_QUESTION;
|
||||
title = "JavaScript Confirm";
|
||||
break;
|
||||
|
||||
case JSDIALOGTYPE_PROMPT:
|
||||
buttons = GTK_BUTTONS_CANCEL;
|
||||
gtk_message_type = GTK_MESSAGE_QUESTION;
|
||||
title = "JavaScript Prompt";
|
||||
break;
|
||||
}
|
||||
|
||||
js_dialog_callback_ = callback;
|
||||
|
||||
if (!origin_url.empty()) {
|
||||
title += " - ";
|
||||
title += origin_url.ToString();
|
||||
}
|
||||
|
||||
GtkWidget* window = GetWindow(browser);
|
||||
DCHECK(window);
|
||||
|
||||
gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window),
|
||||
GTK_DIALOG_MODAL,
|
||||
gtk_message_type,
|
||||
buttons,
|
||||
"%s",
|
||||
message_text.ToString().c_str());
|
||||
g_signal_connect(gtk_dialog_,
|
||||
"delete-event",
|
||||
G_CALLBACK(gtk_widget_hide_on_delete),
|
||||
NULL);
|
||||
|
||||
gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
|
||||
|
||||
GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
|
||||
GTK_STOCK_OK,
|
||||
GTK_RESPONSE_OK);
|
||||
|
||||
if (dialog_type != JSDIALOGTYPE_PROMPT)
|
||||
gtk_widget_grab_focus(ok_button);
|
||||
|
||||
if (dialog_type == JSDIALOGTYPE_PROMPT) {
|
||||
GtkWidget* content_area =
|
||||
gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
|
||||
GtkWidget* text_box = gtk_entry_new();
|
||||
gtk_entry_set_text(GTK_ENTRY(text_box),
|
||||
default_prompt_text.ToString().c_str());
|
||||
gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
|
||||
g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
|
||||
gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
|
||||
}
|
||||
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
|
||||
g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnDialogResponse), this);
|
||||
gtk_widget_show_all(GTK_WIDGET(gtk_dialog_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnBeforeUnloadDialog(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message_text,
|
||||
bool is_reload,
|
||||
CefRefPtr<CefJSDialogCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const std::string& new_message_text =
|
||||
message_text.ToString() + "\n\nIs it OK to leave/reload this page?";
|
||||
bool suppress_message = false;
|
||||
|
||||
return OnJSDialog(browser, CefString(), CefString(), JSDIALOGTYPE_CONFIRM,
|
||||
new_message_text, CefString(), callback, suppress_message);
|
||||
}
|
||||
|
||||
void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!gtk_dialog_)
|
||||
return;
|
||||
gtk_widget_destroy(gtk_dialog_);
|
||||
gtk_dialog_ = NULL;
|
||||
js_dialog_callback_ = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog,
|
||||
gint response_id,
|
||||
ClientDialogHandlerGtk* handler) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_));
|
||||
switch (response_id) {
|
||||
case GTK_RESPONSE_OK:
|
||||
handler->js_dialog_callback_->Continue(true, GetPromptText(dialog));
|
||||
break;
|
||||
case GTK_RESPONSE_CANCEL:
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
handler->js_dialog_callback_->Continue(false, CefString());
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
handler->OnResetDialogState(NULL);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "include/cef_dialog_handler.h"
|
||||
#include "include/cef_jsdialog_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class ClientDialogHandlerGtk : public CefDialogHandler,
|
||||
public CefJSDialogHandler {
|
||||
public:
|
||||
ClientDialogHandlerGtk();
|
||||
|
||||
// CefDialogHandler methods.
|
||||
bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||
FileDialogMode mode,
|
||||
const CefString& title,
|
||||
const CefString& default_file_path,
|
||||
const std::vector<CefString>& accept_filters,
|
||||
int selected_accept_filter,
|
||||
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
|
||||
|
||||
// CefJSDialogHandler methods.
|
||||
bool OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
const CefString& accept_lang,
|
||||
JSDialogType dialog_type,
|
||||
const CefString& message_text,
|
||||
const CefString& default_prompt_text,
|
||||
CefRefPtr<CefJSDialogCallback> callback,
|
||||
bool& suppress_message) OVERRIDE;
|
||||
bool OnBeforeUnloadDialog(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message_text,
|
||||
bool is_reload,
|
||||
CefRefPtr<CefJSDialogCallback> callback) OVERRIDE;
|
||||
void OnResetDialogState(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
||||
private:
|
||||
static void OnDialogResponse(GtkDialog *dialog,
|
||||
gint response_id,
|
||||
ClientDialogHandlerGtk* handler);
|
||||
|
||||
GtkWidget* gtk_dialog_;
|
||||
CefRefPtr<CefJSDialogCallback> js_dialog_callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientDialogHandlerGtk);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientDialogHandlerGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_
|
||||
@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2012 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 "cefclient/browser/dialog_test.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
namespace dialog_test {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestUrl[] = "http://tests/dialogs";
|
||||
const char kFileOpenMessageName[] = "DialogTest.FileOpen";
|
||||
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
|
||||
const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
|
||||
const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#define PATH_SEP '\\'
|
||||
#else
|
||||
#define PATH_SEP '/'
|
||||
#endif
|
||||
|
||||
// Store persistent dialog state information.
|
||||
class DialogState : public base::RefCountedThreadSafe<DialogState> {
|
||||
public:
|
||||
DialogState()
|
||||
: mode_(FILE_DIALOG_OPEN),
|
||||
last_selected_filter_(0),
|
||||
pending_(false) {}
|
||||
|
||||
cef_file_dialog_mode_t mode_;
|
||||
int last_selected_filter_;
|
||||
CefString last_file_;
|
||||
bool pending_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DialogState);
|
||||
};
|
||||
|
||||
// Callback executed when the file dialog is dismissed.
|
||||
class DialogCallback : public CefRunFileDialogCallback {
|
||||
public:
|
||||
DialogCallback(
|
||||
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback,
|
||||
scoped_refptr<DialogState> dialog_state)
|
||||
: router_callback_(router_callback),
|
||||
dialog_state_(dialog_state) {
|
||||
}
|
||||
|
||||
virtual void OnFileDialogDismissed(
|
||||
int last_selected_filter,
|
||||
const std::vector<CefString>& file_paths) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(dialog_state_->pending_);
|
||||
|
||||
if (!file_paths.empty()) {
|
||||
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER)
|
||||
dialog_state_->last_selected_filter_ = last_selected_filter;
|
||||
|
||||
dialog_state_->last_file_ = file_paths[0];
|
||||
if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
|
||||
std::string last_file = dialog_state_->last_file_;
|
||||
if (last_file[last_file.length() - 1] != PATH_SEP) {
|
||||
// Add a trailing slash so we know it's a directory. Otherwise, file
|
||||
// dialogs will think the last path component is a file name.
|
||||
last_file += PATH_SEP;
|
||||
dialog_state_->last_file_ = last_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send a message back to the render process with the list of file paths.
|
||||
std::string response;
|
||||
for (int i = 0; i < static_cast<int>(file_paths.size()); ++i) {
|
||||
if (!response.empty())
|
||||
response += "|"; // Use a delimiter disallowed in file paths.
|
||||
response += file_paths[i];
|
||||
}
|
||||
|
||||
router_callback_->Success(response);
|
||||
router_callback_ = NULL;
|
||||
|
||||
dialog_state_->pending_ = false;
|
||||
dialog_state_ = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback_;
|
||||
scoped_refptr<DialogState> dialog_state_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(DialogCallback);
|
||||
DISALLOW_COPY_AND_ASSIGN(DialogCallback);
|
||||
};
|
||||
|
||||
// Handle messages in the browser process.
|
||||
class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
|
||||
// Called due to cefQuery execution in dialogs.html.
|
||||
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Only handle messages from the test URL.
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestUrl) != 0)
|
||||
return false;
|
||||
|
||||
if (!dialog_state_.get())
|
||||
dialog_state_ = new DialogState;
|
||||
|
||||
// Make sure we're only running one dialog at a time.
|
||||
DCHECK(!dialog_state_->pending_);
|
||||
|
||||
std::vector<CefString> accept_filters;
|
||||
std::string title;
|
||||
|
||||
const std::string& message_name = request;
|
||||
if (message_name == kFileOpenMessageName) {
|
||||
dialog_state_->mode_ = FILE_DIALOG_OPEN;
|
||||
title = "My Open Dialog";
|
||||
} else if (message_name == kFileOpenMultipleMessageName) {
|
||||
dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
|
||||
title = "My Open Multiple Dialog";
|
||||
} else if (message_name == kFileOpenFolderMessageName) {
|
||||
dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
|
||||
title = "My Open Folder Dialog";
|
||||
} else if (message_name == kFileSaveMessageName) {
|
||||
dialog_state_->mode_ = static_cast<cef_file_dialog_mode_t>(
|
||||
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
||||
title = "My Save Dialog";
|
||||
} else {
|
||||
NOTREACHED();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
|
||||
// Build filters based on mime time.
|
||||
accept_filters.push_back("text/*");
|
||||
|
||||
// Build filters based on file extension.
|
||||
accept_filters.push_back(".log");
|
||||
accept_filters.push_back(".patch");
|
||||
|
||||
// Add specific filters as-is.
|
||||
accept_filters.push_back("Document Files|.doc;.odt");
|
||||
accept_filters.push_back("Image Files|.png;.jpg;.gif");
|
||||
accept_filters.push_back("PDF Files|.pdf");
|
||||
}
|
||||
|
||||
dialog_state_->pending_ = true;
|
||||
|
||||
browser->GetHost()->RunFileDialog(
|
||||
dialog_state_->mode_,
|
||||
title,
|
||||
dialog_state_->last_file_,
|
||||
accept_filters,
|
||||
dialog_state_->last_selected_filter_,
|
||||
new DialogCallback(callback, dialog_state_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_refptr<DialogState> dialog_state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Handler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
|
||||
handlers.insert(new Handler());
|
||||
}
|
||||
|
||||
} // namespace dialog_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client {
|
||||
namespace dialog_test {
|
||||
|
||||
// Create message handlers. Called from test_runner.cc.
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
|
||||
|
||||
} // namespace dialog_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_TEST_H_
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/geometry_util.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace client {
|
||||
|
||||
int LogicalToDevice(int value, float device_scale_factor) {
|
||||
float scaled_val = static_cast<float>(value) * device_scale_factor;
|
||||
return static_cast<int>(std::floor(scaled_val));
|
||||
}
|
||||
|
||||
CefRect LogicalToDevice(const CefRect& value, float device_scale_factor) {
|
||||
return CefRect(LogicalToDevice(value.x, device_scale_factor),
|
||||
LogicalToDevice(value.y, device_scale_factor),
|
||||
LogicalToDevice(value.width, device_scale_factor),
|
||||
LogicalToDevice(value.height, device_scale_factor));
|
||||
}
|
||||
|
||||
int DeviceToLogical(int value, float device_scale_factor) {
|
||||
float scaled_val = static_cast<float>(value) / device_scale_factor;
|
||||
return static_cast<int>(std::floor(scaled_val));
|
||||
}
|
||||
|
||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor) {
|
||||
value.x = DeviceToLogical(value.x, device_scale_factor);
|
||||
value.y = DeviceToLogical(value.y, device_scale_factor);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_GEOMETRY_UTIL_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_GEOMETRY_UTIL_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/internal/cef_types_wrappers.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Convert |value| from logical coordinates to device coordinates.
|
||||
int LogicalToDevice(int value, float device_scale_factor);
|
||||
CefRect LogicalToDevice(const CefRect& value, float device_scale_factor);
|
||||
|
||||
// Convert |value| from device coordinates to logical coordinates.
|
||||
int DeviceToLogical(int value, float device_scale_factor);
|
||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_GEOMETRY_UTIL_H_
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/main_context.h"
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
MainContext* g_main_context = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
MainContext* MainContext::Get() {
|
||||
DCHECK(g_main_context);
|
||||
return g_main_context;
|
||||
}
|
||||
|
||||
MainContext::MainContext() {
|
||||
DCHECK(!g_main_context);
|
||||
g_main_context = this;
|
||||
|
||||
}
|
||||
|
||||
MainContext::~MainContext() {
|
||||
g_main_context = NULL;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/internal/cef_types_wrappers.h"
|
||||
#include "cefclient/browser/osr_renderer.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class RootWindowManager;
|
||||
|
||||
// Used to store global context in the browser process. The methods of this
|
||||
// class are thread-safe unless otherwise indicated.
|
||||
class MainContext {
|
||||
public:
|
||||
// Returns the singleton instance of this object.
|
||||
static MainContext* Get();
|
||||
|
||||
// Returns the full path to the console log file.
|
||||
virtual std::string GetConsoleLogPath() = 0;
|
||||
|
||||
// Returns the full path to |file_name|.
|
||||
virtual std::string GetDownloadPath(const std::string& file_name) = 0;
|
||||
|
||||
// Returns the app working directory including trailing path separator.
|
||||
virtual std::string GetAppWorkingDirectory() = 0;
|
||||
|
||||
// Returns the main application URL.
|
||||
virtual std::string GetMainURL() = 0;
|
||||
|
||||
// Returns the background color.
|
||||
virtual cef_color_t GetBackgroundColor() = 0;
|
||||
|
||||
// Populate |settings| based on command-line arguments.
|
||||
virtual void PopulateSettings(CefSettings* settings) = 0;
|
||||
virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0;
|
||||
virtual void PopulateOsrSettings(OsrRenderer::Settings* settings) = 0;
|
||||
|
||||
// Returns the object used to create/manage RootWindow instances.
|
||||
virtual RootWindowManager* GetRootWindowManager() = 0;
|
||||
|
||||
protected:
|
||||
MainContext();
|
||||
virtual ~MainContext();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MainContext);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_H_
|
||||
@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/main_context_impl.h"
|
||||
|
||||
#include "include/cef_parser.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
// The default URL to load in a browser window.
|
||||
const char kDefaultUrl[] = "http://www.google.com";
|
||||
|
||||
} // namespace
|
||||
|
||||
MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
|
||||
bool terminate_when_all_windows_closed)
|
||||
: command_line_(command_line),
|
||||
terminate_when_all_windows_closed_(terminate_when_all_windows_closed),
|
||||
initialized_(false),
|
||||
shutdown_(false),
|
||||
background_color_(CefColorSetARGB(255, 255, 255, 255)) {
|
||||
DCHECK(command_line_.get());
|
||||
|
||||
// Set the main URL.
|
||||
if (command_line_->HasSwitch(switches::kUrl))
|
||||
main_url_ = command_line_->GetSwitchValue(switches::kUrl);
|
||||
if (main_url_.empty())
|
||||
main_url_ = kDefaultUrl;
|
||||
|
||||
if (command_line_->HasSwitch(switches::kBackgroundColor)) {
|
||||
// Parse the background color value.
|
||||
CefParseCSSColor(command_line_->GetSwitchValue(switches::kBackgroundColor),
|
||||
false, background_color_);
|
||||
}
|
||||
}
|
||||
|
||||
MainContextImpl::~MainContextImpl() {
|
||||
// The context must either not have been initialized, or it must have also
|
||||
// been shut down.
|
||||
DCHECK(!initialized_ || shutdown_);
|
||||
}
|
||||
|
||||
std::string MainContextImpl::GetConsoleLogPath() {
|
||||
return GetAppWorkingDirectory() + "console.log";
|
||||
}
|
||||
|
||||
std::string MainContextImpl::GetMainURL() {
|
||||
return main_url_;
|
||||
}
|
||||
|
||||
cef_color_t MainContextImpl::GetBackgroundColor() {
|
||||
return background_color_;
|
||||
}
|
||||
|
||||
void MainContextImpl::PopulateSettings(CefSettings* settings) {
|
||||
#if defined(OS_WIN)
|
||||
settings->multi_threaded_message_loop =
|
||||
command_line_->HasSwitch(switches::kMultiThreadedMessageLoop);
|
||||
#endif
|
||||
|
||||
CefString(&settings->cache_path) =
|
||||
command_line_->GetSwitchValue(switches::kCachePath);
|
||||
|
||||
if (command_line_->HasSwitch(switches::kOffScreenRenderingEnabled))
|
||||
settings->windowless_rendering_enabled = true;
|
||||
|
||||
settings->background_color = background_color_;
|
||||
}
|
||||
|
||||
void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) {
|
||||
if (command_line_->HasSwitch(switches::kOffScreenFrameRate)) {
|
||||
settings->windowless_frame_rate = atoi(command_line_->
|
||||
GetSwitchValue(switches::kOffScreenFrameRate).ToString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void MainContextImpl::PopulateOsrSettings(OsrRenderer::Settings* settings) {
|
||||
settings->transparent =
|
||||
command_line_->HasSwitch(switches::kTransparentPaintingEnabled);
|
||||
settings->show_update_rect =
|
||||
command_line_->HasSwitch(switches::kShowUpdateRect);
|
||||
settings->background_color = background_color_;
|
||||
}
|
||||
|
||||
RootWindowManager* MainContextImpl::GetRootWindowManager() {
|
||||
DCHECK(InValidState());
|
||||
return root_window_manager_.get();
|
||||
}
|
||||
|
||||
bool MainContextImpl::Initialize(const CefMainArgs& args,
|
||||
const CefSettings& settings,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(!initialized_);
|
||||
DCHECK(!shutdown_);
|
||||
|
||||
if (!CefInitialize(args, settings, application, windows_sandbox_info))
|
||||
return false;
|
||||
|
||||
// Need to create the RootWindowManager after calling CefInitialize because
|
||||
// TempWindowX11 uses cef_get_xdisplay().
|
||||
root_window_manager_.reset(
|
||||
new RootWindowManager(terminate_when_all_windows_closed_));
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainContextImpl::Shutdown() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(initialized_);
|
||||
DCHECK(!shutdown_);
|
||||
|
||||
root_window_manager_.reset();
|
||||
|
||||
CefShutdown();
|
||||
|
||||
shutdown_ = true;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/base/cef_thread_checker.h"
|
||||
#include "include/cef_app.h"
|
||||
#include "include/cef_command_line.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/root_window_manager.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Used to store global context in the browser process.
|
||||
class MainContextImpl : public MainContext {
|
||||
public:
|
||||
MainContextImpl(CefRefPtr<CefCommandLine> command_line,
|
||||
bool terminate_when_all_windows_closed);
|
||||
|
||||
// MainContext members.
|
||||
std::string GetConsoleLogPath() OVERRIDE;
|
||||
std::string GetDownloadPath(const std::string& file_name) OVERRIDE;
|
||||
std::string GetAppWorkingDirectory() OVERRIDE;
|
||||
std::string GetMainURL() OVERRIDE;
|
||||
cef_color_t GetBackgroundColor() OVERRIDE;
|
||||
void PopulateSettings(CefSettings* settings) OVERRIDE;
|
||||
void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE;
|
||||
void PopulateOsrSettings(OsrRenderer::Settings* settings) OVERRIDE;
|
||||
RootWindowManager* GetRootWindowManager() OVERRIDE;
|
||||
|
||||
// Initialize CEF and associated main context state. This method must be
|
||||
// called on the same thread that created this object.
|
||||
bool Initialize(const CefMainArgs& args,
|
||||
const CefSettings& settings,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info);
|
||||
|
||||
// Shut down CEF and associated context state. This method must be called on
|
||||
// the same thread that created this object.
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<MainContextImpl>;
|
||||
|
||||
~MainContextImpl();
|
||||
|
||||
// Returns true if the context is in a valid state (initialized and not yet
|
||||
// shut down).
|
||||
bool InValidState() const {
|
||||
return initialized_ && !shutdown_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefCommandLine> command_line_;
|
||||
const bool terminate_when_all_windows_closed_;
|
||||
|
||||
// Track context state. Accessing these variables from multiple threads is
|
||||
// safe because only a single thread will exist at the time that they're set
|
||||
// (during context initialization and shutdown).
|
||||
bool initialized_;
|
||||
bool shutdown_;
|
||||
|
||||
std::string main_url_;
|
||||
cef_color_t background_color_;
|
||||
|
||||
scoped_ptr<RootWindowManager> root_window_manager_;
|
||||
|
||||
// Used to verify that methods are called on the correct thread.
|
||||
base::ThreadChecker thread_checker_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MainContextImpl);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_
|
||||
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/main_context_impl.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace client {
|
||||
|
||||
std::string MainContextImpl::GetDownloadPath(const std::string& file_name) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string MainContextImpl::GetAppWorkingDirectory() {
|
||||
char szWorkingDir[256];
|
||||
if (getcwd(szWorkingDir, sizeof(szWorkingDir) - 1) == NULL) {
|
||||
szWorkingDir[0] = 0;
|
||||
} else {
|
||||
// Add trailing path separator.
|
||||
size_t len = strlen(szWorkingDir);
|
||||
szWorkingDir[len] = '/';
|
||||
szWorkingDir[len + 1] = 0;
|
||||
}
|
||||
return szWorkingDir;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/main_message_loop.h"
|
||||
|
||||
#include "include/cef_task.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
MainMessageLoop* g_main_message_loop = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
MainMessageLoop::MainMessageLoop() {
|
||||
DCHECK(!g_main_message_loop);
|
||||
g_main_message_loop = this;
|
||||
}
|
||||
|
||||
MainMessageLoop::~MainMessageLoop() {
|
||||
g_main_message_loop = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
MainMessageLoop* MainMessageLoop::Get() {
|
||||
DCHECK(g_main_message_loop);
|
||||
return g_main_message_loop;
|
||||
}
|
||||
|
||||
void MainMessageLoop::PostClosure(const base::Closure& closure) {
|
||||
PostTask(CefCreateClosureTask(closure));
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_task.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents the message loop running on the main application thread in the
|
||||
// browser process. This will be the same as the CEF UI thread on Linux, OS X
|
||||
// and Windows when not using multi-threaded message loop mode. The methods of
|
||||
// this class are thread-safe unless otherwise indicated.
|
||||
class MainMessageLoop {
|
||||
public:
|
||||
// Returns the singleton instance of this object.
|
||||
static MainMessageLoop* Get();
|
||||
|
||||
// Run the message loop. The thread that this method is called on will be
|
||||
// considered the main thread. This blocks until Quit() is called.
|
||||
virtual int Run() = 0;
|
||||
|
||||
// Quit the message loop.
|
||||
virtual void Quit() = 0;
|
||||
|
||||
// Post a task for execution on the main message loop.
|
||||
virtual void PostTask(CefRefPtr<CefTask> task) = 0;
|
||||
|
||||
// Returns true if this message loop runs tasks on the current thread.
|
||||
virtual bool RunsTasksOnCurrentThread() const = 0;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Set the current modeless dialog on Windows for proper delivery of dialog
|
||||
// messages when using multi-threaded message loop mode. This method must be
|
||||
// called from the main thread. See http://support.microsoft.com/kb/71450 for
|
||||
// background.
|
||||
virtual void SetCurrentModelessDialog(HWND hWndDialog) = 0;
|
||||
#endif
|
||||
|
||||
// Post a closure for execution on the main message loop.
|
||||
void PostClosure(const base::Closure& closure);
|
||||
|
||||
protected:
|
||||
// Only allow deletion via scoped_ptr.
|
||||
friend struct base::DefaultDeleter<MainMessageLoop>;
|
||||
|
||||
MainMessageLoop();
|
||||
virtual ~MainMessageLoop();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MainMessageLoop);
|
||||
};
|
||||
|
||||
#define CURRENTLY_ON_MAIN_THREAD() \
|
||||
client::MainMessageLoop::Get()->RunsTasksOnCurrentThread()
|
||||
|
||||
#define REQUIRE_MAIN_THREAD() DCHECK(CURRENTLY_ON_MAIN_THREAD())
|
||||
|
||||
#define MAIN_POST_TASK(task) \
|
||||
client::MainMessageLoop::Get()->PostTask(task)
|
||||
|
||||
#define MAIN_POST_CLOSURE(closure) \
|
||||
client::MainMessageLoop::Get()->PostClosure(closure)
|
||||
|
||||
// Use this struct in conjuction with RefCountedThreadSafe to ensure that an
|
||||
// object is deleted on the main thread. For example:
|
||||
//
|
||||
// class Foo : public base::RefCountedThreadSafe<Foo, DeleteOnMainThread> {
|
||||
// public:
|
||||
// Foo();
|
||||
// void DoSomething();
|
||||
//
|
||||
// private:
|
||||
// // Allow deletion via scoped_refptr only.
|
||||
// friend struct DeleteOnMainThread;
|
||||
// friend class base::RefCountedThreadSafe<Foo, DeleteOnMainThread>;
|
||||
//
|
||||
// virtual ~Foo() {}
|
||||
// };
|
||||
//
|
||||
// base::scoped_refptr<Foo> foo = new Foo();
|
||||
// foo->DoSomething();
|
||||
// foo = NULL; // Deletion of |foo| will occur on the main thread.
|
||||
//
|
||||
struct DeleteOnMainThread {
|
||||
template<typename T>
|
||||
static void Destruct(const T* x) {
|
||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||
delete x;
|
||||
} else {
|
||||
client::MainMessageLoop::Get()->PostClosure(
|
||||
base::Bind(&DeleteOnMainThread::Destruct<T>, x));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_H_
|
||||
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/main_message_loop_std.h"
|
||||
|
||||
#include "include/cef_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
MainMessageLoopStd::MainMessageLoopStd() {
|
||||
}
|
||||
|
||||
int MainMessageLoopStd::Run() {
|
||||
CefRunMessageLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MainMessageLoopStd::Quit() {
|
||||
CefQuitMessageLoop();
|
||||
}
|
||||
|
||||
void MainMessageLoopStd::PostTask(CefRefPtr<CefTask> task) {
|
||||
CefPostTask(TID_UI, task);
|
||||
}
|
||||
|
||||
bool MainMessageLoopStd::RunsTasksOnCurrentThread() const {
|
||||
return CefCurrentlyOn(TID_UI);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void MainMessageLoopStd::SetCurrentModelessDialog(HWND hWndDialog) {
|
||||
// Nothing to do here. The Chromium message loop implementation will
|
||||
// internally route dialog messages.
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_STD_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_STD_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents the main message loop in the browser process. This implementation
|
||||
// is a light-weight wrapper around the Chromium UI thread.
|
||||
class MainMessageLoopStd : public MainMessageLoop {
|
||||
public:
|
||||
MainMessageLoopStd();
|
||||
|
||||
// MainMessageLoop methods.
|
||||
int Run() OVERRIDE;
|
||||
void Quit() OVERRIDE;
|
||||
void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
|
||||
bool RunsTasksOnCurrentThread() const OVERRIDE;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void SetCurrentModelessDialog(HWND hWndDialog) OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MainMessageLoopStd);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_STD_H_
|
||||
@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2014 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 CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_render_handler.h"
|
||||
#include "cefclient/browser/client_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class OsrDragEvents {
|
||||
public:
|
||||
virtual CefBrowserHost::DragOperationsMask OnDragEnter(
|
||||
CefRefPtr<CefDragData> drag_data,
|
||||
CefMouseEvent ev,
|
||||
CefBrowserHost::DragOperationsMask effect) = 0;
|
||||
|
||||
virtual CefBrowserHost::DragOperationsMask OnDragOver(
|
||||
CefMouseEvent ev,
|
||||
CefBrowserHost::DragOperationsMask effect) = 0;
|
||||
|
||||
virtual void OnDragLeave() = 0;
|
||||
|
||||
virtual CefBrowserHost::DragOperationsMask OnDrop(
|
||||
CefMouseEvent ev,
|
||||
CefBrowserHost::DragOperationsMask effect) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~OsrDragEvents() {}
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_
|
||||
@ -0,0 +1,350 @@
|
||||
// Copyright (c) 2012 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 "cefclient/browser/osr_renderer.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#elif defined(OS_MACOSX)
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(OS_LINUX)
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#else
|
||||
#error Platform is not supported.
|
||||
#endif
|
||||
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
#ifndef GL_BGR
|
||||
#define GL_BGR 0x80E0
|
||||
#endif
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
|
||||
#endif
|
||||
|
||||
// DCHECK on gl errors.
|
||||
#ifndef NDEBUG
|
||||
#define VERIFY_NO_ERROR { \
|
||||
int _gl_error = glGetError(); \
|
||||
DCHECK(_gl_error == GL_NO_ERROR) << \
|
||||
"glGetError returned " << _gl_error; \
|
||||
}
|
||||
#else
|
||||
#define VERIFY_NO_ERROR
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
OsrRenderer::Settings::Settings()
|
||||
: transparent(false),
|
||||
show_update_rect(false),
|
||||
background_color(CefColorSetARGB(255, 255, 255, 255)) {
|
||||
}
|
||||
|
||||
OsrRenderer::OsrRenderer(const Settings& settings)
|
||||
: settings_(settings),
|
||||
initialized_(false),
|
||||
texture_id_(0),
|
||||
view_width_(0),
|
||||
view_height_(0),
|
||||
spin_x_(0),
|
||||
spin_y_(0) {
|
||||
}
|
||||
|
||||
OsrRenderer::~OsrRenderer() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void OsrRenderer::Initialize() {
|
||||
if (initialized_)
|
||||
return;
|
||||
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); VERIFY_NO_ERROR;
|
||||
|
||||
glClearColor(float(CefColorGetR(settings_.background_color)) / 255.0f,
|
||||
float(CefColorGetG(settings_.background_color)) / 255.0f,
|
||||
float(CefColorGetB(settings_.background_color)) / 255.0f,
|
||||
1.0f); VERIFY_NO_ERROR;
|
||||
|
||||
// Necessary for non-power-of-2 textures to render correctly.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); VERIFY_NO_ERROR;
|
||||
|
||||
// Create the texture.
|
||||
glGenTextures(1, &texture_id_); VERIFY_NO_ERROR;
|
||||
DCHECK_NE(texture_id_, 0U); VERIFY_NO_ERROR;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_NEAREST); VERIFY_NO_ERROR;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
GL_NEAREST); VERIFY_NO_ERROR;
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); VERIFY_NO_ERROR;
|
||||
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void OsrRenderer::Cleanup() {
|
||||
if (texture_id_ != 0)
|
||||
glDeleteTextures(1, &texture_id_);
|
||||
}
|
||||
|
||||
void OsrRenderer::Render() {
|
||||
if (view_width_ == 0 || view_height_ == 0)
|
||||
return;
|
||||
|
||||
DCHECK(initialized_);
|
||||
|
||||
struct {
|
||||
float tu, tv;
|
||||
float x, y, z;
|
||||
} static vertices[] = {
|
||||
{0.0f, 1.0f, -1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 1.0f, 1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f, 1.0f, 0.0f}
|
||||
};
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); VERIFY_NO_ERROR;
|
||||
|
||||
glMatrixMode(GL_MODELVIEW); VERIFY_NO_ERROR;
|
||||
glLoadIdentity(); VERIFY_NO_ERROR;
|
||||
|
||||
// Match GL units to screen coordinates.
|
||||
glViewport(0, 0, view_width_, view_height_); VERIFY_NO_ERROR;
|
||||
glMatrixMode(GL_PROJECTION); VERIFY_NO_ERROR;
|
||||
glLoadIdentity(); VERIFY_NO_ERROR;
|
||||
|
||||
// Draw the background gradient.
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS); VERIFY_NO_ERROR;
|
||||
// Don't check for errors until glEnd().
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0, 0.0, 0.0, 1.0); // red
|
||||
glVertex2f(-1.0, -1.0);
|
||||
glVertex2f(1.0, -1.0);
|
||||
glColor4f(0.0, 0.0, 1.0, 1.0); // blue
|
||||
glVertex2f(1.0, 1.0);
|
||||
glVertex2f(-1.0, 1.0);
|
||||
glEnd(); VERIFY_NO_ERROR;
|
||||
glPopAttrib(); VERIFY_NO_ERROR;
|
||||
|
||||
// Rotate the view based on the mouse spin.
|
||||
if (spin_x_ != 0) {
|
||||
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f); VERIFY_NO_ERROR;
|
||||
}
|
||||
if (spin_y_ != 0) {
|
||||
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f); VERIFY_NO_ERROR;
|
||||
}
|
||||
|
||||
if (settings_.transparent) {
|
||||
// Alpha blending style. Texture values have premultiplied alpha.
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); VERIFY_NO_ERROR;
|
||||
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND); VERIFY_NO_ERROR;
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
|
||||
|
||||
// Draw the facets with the texture.
|
||||
DCHECK_NE(texture_id_, 0U); VERIFY_NO_ERROR;
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
|
||||
glInterleavedArrays(GL_T2F_V3F, 0, vertices); VERIFY_NO_ERROR;
|
||||
glDrawArrays(GL_QUADS, 0, 4); VERIFY_NO_ERROR;
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
|
||||
|
||||
if (settings_.transparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND); VERIFY_NO_ERROR;
|
||||
}
|
||||
|
||||
// Draw a rectangle around the update region.
|
||||
if (settings_.show_update_rect && !update_rect_.IsEmpty()) {
|
||||
int left = update_rect_.x;
|
||||
int right = update_rect_.x + update_rect_.width;
|
||||
int top = update_rect_.y;
|
||||
int bottom = update_rect_.y + update_rect_.height;
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// Shrink the box so that top & right sides are drawn.
|
||||
top += 1;
|
||||
right -= 1;
|
||||
#else
|
||||
// Shrink the box so that left & bottom sides are drawn.
|
||||
left += 1;
|
||||
bottom -= 1;
|
||||
#endif
|
||||
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS); VERIFY_NO_ERROR
|
||||
glMatrixMode(GL_PROJECTION); VERIFY_NO_ERROR;
|
||||
glPushMatrix(); VERIFY_NO_ERROR;
|
||||
glLoadIdentity(); VERIFY_NO_ERROR;
|
||||
glOrtho(0, view_width_, view_height_, 0, 0, 1); VERIFY_NO_ERROR;
|
||||
|
||||
glLineWidth(1); VERIFY_NO_ERROR;
|
||||
glColor3f(1.0f, 0.0f, 0.0f); VERIFY_NO_ERROR;
|
||||
// Don't check for errors until glEnd().
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2i(left, top);
|
||||
glVertex2i(right, top);
|
||||
glVertex2i(right, bottom);
|
||||
glVertex2i(left, bottom);
|
||||
glVertex2i(left, top);
|
||||
glEnd(); VERIFY_NO_ERROR;
|
||||
|
||||
glPopMatrix(); VERIFY_NO_ERROR;
|
||||
glPopAttrib(); VERIFY_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void OsrRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) {
|
||||
if (!show) {
|
||||
// Clear the popup rectangle.
|
||||
ClearPopupRects();
|
||||
}
|
||||
}
|
||||
|
||||
void OsrRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) {
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
return;
|
||||
original_popup_rect_ = rect;
|
||||
popup_rect_ = GetPopupRectInWebView(original_popup_rect_);
|
||||
}
|
||||
|
||||
CefRect OsrRenderer::GetPopupRectInWebView(const CefRect& original_rect) {
|
||||
CefRect rc(original_rect);
|
||||
// if x or y are negative, move them to 0.
|
||||
if (rc.x < 0)
|
||||
rc.x = 0;
|
||||
if (rc.y < 0)
|
||||
rc.y = 0;
|
||||
// if popup goes outside the view, try to reposition origin
|
||||
if (rc.x + rc.width > view_width_)
|
||||
rc.x = view_width_ - rc.width;
|
||||
if (rc.y + rc.height > view_height_)
|
||||
rc.y = view_height_ - rc.height;
|
||||
// if x or y became negative, move them to 0 again.
|
||||
if (rc.x < 0)
|
||||
rc.x = 0;
|
||||
if (rc.y < 0)
|
||||
rc.y = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void OsrRenderer::ClearPopupRects() {
|
||||
popup_rect_.Set(0, 0, 0, 0);
|
||||
original_popup_rect_.Set(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void OsrRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer, int width, int height) {
|
||||
if (!initialized_)
|
||||
Initialize();
|
||||
|
||||
if (settings_.transparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND); VERIFY_NO_ERROR;
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
|
||||
|
||||
DCHECK_NE(texture_id_, 0U);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
|
||||
|
||||
if (type == PET_VIEW) {
|
||||
int old_width = view_width_;
|
||||
int old_height = view_height_;
|
||||
|
||||
view_width_ = width;
|
||||
view_height_ = height;
|
||||
|
||||
if (settings_.show_update_rect)
|
||||
update_rect_ = dirtyRects[0];
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_); VERIFY_NO_ERROR;
|
||||
|
||||
if (old_width != view_width_ || old_height != view_height_ ||
|
||||
(dirtyRects.size() == 1 &&
|
||||
dirtyRects[0] == CefRect(0, 0, view_width_, view_height_))) {
|
||||
// Update/resize the whole texture.
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); VERIFY_NO_ERROR;
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); VERIFY_NO_ERROR;
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA, view_width_, view_height_, 0,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); VERIFY_NO_ERROR;
|
||||
} else {
|
||||
// Update just the dirty rectangles.
|
||||
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
const CefRect& rect = *i;
|
||||
DCHECK(rect.x + rect.width <= view_width_);
|
||||
DCHECK(rect.y + rect.height <= view_height_);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x); VERIFY_NO_ERROR;
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y); VERIFY_NO_ERROR;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width,
|
||||
rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
buffer); VERIFY_NO_ERROR;
|
||||
}
|
||||
}
|
||||
} else if (type == PET_POPUP && popup_rect_.width > 0 &&
|
||||
popup_rect_.height > 0) {
|
||||
int skip_pixels = 0, x = popup_rect_.x;
|
||||
int skip_rows = 0, y = popup_rect_.y;
|
||||
int w = width;
|
||||
int h = height;
|
||||
|
||||
// Adjust the popup to fit inside the view.
|
||||
if (x < 0) {
|
||||
skip_pixels = -x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
skip_rows = -y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + w > view_width_)
|
||||
w -= x + w - view_width_;
|
||||
if (y + h > view_height_)
|
||||
h -= y + h - view_height_;
|
||||
|
||||
// Update the popup rectangle.
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, width); VERIFY_NO_ERROR;
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); VERIFY_NO_ERROR;
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); VERIFY_NO_ERROR;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, buffer); VERIFY_NO_ERROR;
|
||||
}
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
|
||||
|
||||
if (settings_.transparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND); VERIFY_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void OsrRenderer::SetSpin(float spinX, float spinY) {
|
||||
spin_x_ = spinX;
|
||||
spin_y_ = spinY;
|
||||
}
|
||||
|
||||
void OsrRenderer::IncrementSpin(float spinDX, float spinDY) {
|
||||
spin_x_ -= spinDX;
|
||||
spin_y_ -= spinDY;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_BROWSER_OSR_RENDERER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_RENDERER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/cef_render_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class OsrRenderer {
|
||||
public:
|
||||
struct Settings {
|
||||
Settings();
|
||||
|
||||
// If true use transparent rendering.
|
||||
bool transparent;
|
||||
|
||||
// If true draw a border around update rectangles.
|
||||
bool show_update_rect;
|
||||
|
||||
// Background color.
|
||||
cef_color_t background_color;
|
||||
};
|
||||
|
||||
explicit OsrRenderer(const Settings& settings);
|
||||
~OsrRenderer();
|
||||
|
||||
// Initialize the OpenGL environment.
|
||||
void Initialize();
|
||||
|
||||
// Clean up the OpenGL environment.
|
||||
void Cleanup();
|
||||
|
||||
// Render to the screen.
|
||||
void Render();
|
||||
|
||||
// Forwarded from CefRenderHandler callbacks.
|
||||
void OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show);
|
||||
// |rect| must be in pixel coordinates.
|
||||
void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect);
|
||||
void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer, int width, int height);
|
||||
|
||||
// Apply spin.
|
||||
void SetSpin(float spinX, float spinY);
|
||||
void IncrementSpin(float spinDX, float spinDY);
|
||||
|
||||
bool IsTransparent() const { return settings_.transparent; }
|
||||
cef_color_t GetBackgroundColor() const { return settings_.background_color; }
|
||||
|
||||
int GetViewWidth() const { return view_width_; }
|
||||
int GetViewHeight() const { return view_height_; }
|
||||
|
||||
const CefRect& popup_rect() const { return popup_rect_; }
|
||||
const CefRect& original_popup_rect() const { return original_popup_rect_; }
|
||||
|
||||
CefRect GetPopupRectInWebView(const CefRect& original_rect);
|
||||
void ClearPopupRects();
|
||||
|
||||
private:
|
||||
const Settings settings_;
|
||||
bool initialized_;
|
||||
unsigned int texture_id_;
|
||||
int view_width_;
|
||||
int view_height_;
|
||||
CefRect popup_rect_;
|
||||
CefRect original_popup_rect_;
|
||||
float spin_x_;
|
||||
float spin_y_;
|
||||
CefRect update_rect_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OsrRenderer);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_RENDERER_H_
|
||||
|
||||
@ -0,0 +1,537 @@
|
||||
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
||||
// Portions Copyright (c) 2012 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 "cefclient/browser/print_handler_gtk.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
// CUPS Duplex attribute and values.
|
||||
const char kCUPSDuplex[] = "cups-Duplex";
|
||||
const char kDuplexNone[] = "None";
|
||||
const char kDuplexTumble[] = "DuplexTumble";
|
||||
const char kDuplexNoTumble[] = "DuplexNoTumble";
|
||||
|
||||
// CUPS color mode attribute and values.
|
||||
const char kCUPSColorMode[] = "cups-ColorMode";
|
||||
const char kCUPSColorModel[] = "cups-ColorModel";
|
||||
const char kCUPSPrintoutMode[] = "cups-PrintoutMode";
|
||||
const char kCUPSProcessColorModel[] = "cups-ProcessColorModel";
|
||||
const char kBlack[] = "Black";
|
||||
const char kCMYK[] = "CMYK";
|
||||
const char kCMY_K[] = "CMY+K";
|
||||
const char kCMY[] = "CMY";
|
||||
const char kColor[] = "Color";
|
||||
const char kGray[] = "Gray";
|
||||
const char kGrayscale[] = "Grayscale";
|
||||
const char kGreyscale[] = "Greyscale";
|
||||
const char kMonochrome[] = "Monochrome";
|
||||
const char kNormal[] = "Normal";
|
||||
const char kNormalGray[] = "Normal.Gray";
|
||||
const char kRGB[] = "RGB";
|
||||
const char kRGBA[] = "RGBA";
|
||||
const char kRGB16[] = "RGB16";
|
||||
|
||||
// Default margin settings.
|
||||
const double kTopMarginInInch = 0.25;
|
||||
const double kBottomMarginInInch = 0.56;
|
||||
const double kLeftMarginInInch = 0.25;
|
||||
const double kRightMarginInInch = 0.25;
|
||||
|
||||
// Length of an inch in CSS's 1px unit.
|
||||
// http://dev.w3.org/csswg/css3-values/#the-px-unit
|
||||
const int kPixelsPerInch = 96;
|
||||
|
||||
// LETTER: 8.5 x 11 inches
|
||||
const float kLetterWidthInch = 8.5f;
|
||||
const float kLetterHeightInch = 11.0f;
|
||||
|
||||
class StickyPrintSettingGtk {
|
||||
public:
|
||||
StickyPrintSettingGtk() : last_used_settings_(gtk_print_settings_new()) {
|
||||
}
|
||||
~StickyPrintSettingGtk() {
|
||||
NOTREACHED(); // The instance is intentionally leaked.
|
||||
}
|
||||
|
||||
GtkPrintSettings* settings() {
|
||||
return last_used_settings_;
|
||||
}
|
||||
|
||||
void SetLastUsedSettings(GtkPrintSettings* settings) {
|
||||
DCHECK(last_used_settings_);
|
||||
g_object_unref(last_used_settings_);
|
||||
last_used_settings_ = gtk_print_settings_copy(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
GtkPrintSettings* last_used_settings_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StickyPrintSettingGtk);
|
||||
};
|
||||
|
||||
// Lazily initialize the singleton instance.
|
||||
StickyPrintSettingGtk* GetLastUsedSettings() {
|
||||
static StickyPrintSettingGtk* settings = NULL;
|
||||
if (!settings)
|
||||
settings = new StickyPrintSettingGtk();
|
||||
return settings;
|
||||
}
|
||||
|
||||
// Helper class to track GTK printers.
|
||||
class GtkPrinterList {
|
||||
public:
|
||||
GtkPrinterList() : default_printer_(NULL) {
|
||||
gtk_enumerate_printers(SetPrinter, this, NULL, TRUE);
|
||||
}
|
||||
|
||||
~GtkPrinterList() {
|
||||
for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
|
||||
it < printers_.end(); ++it) {
|
||||
g_object_unref(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Can return NULL if there's no default printer. E.g. Printer on a laptop
|
||||
// is "home_printer", but the laptop is at work.
|
||||
GtkPrinter* default_printer() {
|
||||
return default_printer_;
|
||||
}
|
||||
|
||||
// Can return NULL if the printer cannot be found due to:
|
||||
// - Printer list out of sync with printer dialog UI.
|
||||
// - Querying for non-existant printers like 'Print to PDF'.
|
||||
GtkPrinter* GetPrinterWithName(const std::string& name) {
|
||||
if (name.empty())
|
||||
return NULL;
|
||||
|
||||
for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
|
||||
it < printers_.end(); ++it) {
|
||||
if (gtk_printer_get_name(*it) == name) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
// Callback function used by gtk_enumerate_printers() to get all printer.
|
||||
static gboolean SetPrinter(GtkPrinter* printer, gpointer data) {
|
||||
GtkPrinterList* printer_list = reinterpret_cast<GtkPrinterList*>(data);
|
||||
if (gtk_printer_is_default(printer))
|
||||
printer_list->default_printer_ = printer;
|
||||
|
||||
g_object_ref(printer);
|
||||
printer_list->printers_.push_back(printer);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
std::vector<GtkPrinter*> printers_;
|
||||
GtkPrinter* default_printer_;
|
||||
};
|
||||
|
||||
void GetColorModelForMode(CefPrintSettings::ColorModel color_mode,
|
||||
std::string* color_setting_name,
|
||||
std::string* color_value) {
|
||||
color_setting_name->assign(kCUPSColorModel);
|
||||
switch (color_mode) {
|
||||
case COLOR_MODEL_COLOR:
|
||||
color_value->assign(kColor);
|
||||
break;
|
||||
case COLOR_MODEL_CMYK:
|
||||
color_value->assign(kCMYK);
|
||||
break;
|
||||
case COLOR_MODEL_PRINTOUTMODE_NORMAL:
|
||||
color_value->assign(kNormal);
|
||||
color_setting_name->assign(kCUPSPrintoutMode);
|
||||
break;
|
||||
case COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY:
|
||||
color_value->assign(kNormalGray);
|
||||
color_setting_name->assign(kCUPSPrintoutMode);
|
||||
break;
|
||||
case COLOR_MODEL_RGB16:
|
||||
color_value->assign(kRGB16);
|
||||
break;
|
||||
case COLOR_MODEL_RGBA:
|
||||
color_value->assign(kRGBA);
|
||||
break;
|
||||
case COLOR_MODEL_RGB:
|
||||
color_value->assign(kRGB);
|
||||
break;
|
||||
case COLOR_MODEL_CMY:
|
||||
color_value->assign(kCMY);
|
||||
break;
|
||||
case COLOR_MODEL_CMY_K:
|
||||
color_value->assign(kCMY_K);
|
||||
break;
|
||||
case COLOR_MODEL_BLACK:
|
||||
color_value->assign(kBlack);
|
||||
break;
|
||||
case COLOR_MODEL_GRAY:
|
||||
color_value->assign(kGray);
|
||||
break;
|
||||
case COLOR_MODEL_COLORMODE_COLOR:
|
||||
color_setting_name->assign(kCUPSColorMode);
|
||||
color_value->assign(kColor);
|
||||
break;
|
||||
case COLOR_MODEL_COLORMODE_MONOCHROME:
|
||||
color_setting_name->assign(kCUPSColorMode);
|
||||
color_value->assign(kMonochrome);
|
||||
break;
|
||||
case COLOR_MODEL_HP_COLOR_COLOR:
|
||||
color_setting_name->assign(kColor);
|
||||
color_value->assign(kColor);
|
||||
break;
|
||||
case COLOR_MODEL_HP_COLOR_BLACK:
|
||||
color_setting_name->assign(kColor);
|
||||
color_value->assign(kBlack);
|
||||
break;
|
||||
case COLOR_MODEL_PROCESSCOLORMODEL_CMYK:
|
||||
color_setting_name->assign(kCUPSProcessColorModel);
|
||||
color_value->assign(kCMYK);
|
||||
break;
|
||||
case COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE:
|
||||
color_setting_name->assign(kCUPSProcessColorModel);
|
||||
color_value->assign(kGreyscale);
|
||||
break;
|
||||
case COLOR_MODEL_PROCESSCOLORMODEL_RGB:
|
||||
color_setting_name->assign(kCUPSProcessColorModel);
|
||||
color_value->assign(kRGB);
|
||||
break;
|
||||
default:
|
||||
color_value->assign(kGrayscale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InitPrintSettings(GtkPrintSettings* settings,
|
||||
GtkPageSetup* page_setup,
|
||||
CefRefPtr<CefPrintSettings> print_settings) {
|
||||
DCHECK(settings);
|
||||
DCHECK(page_setup);
|
||||
|
||||
std::string device_name;
|
||||
const gchar* name = gtk_print_settings_get_printer(settings);
|
||||
if (name)
|
||||
device_name = name;
|
||||
print_settings->SetDeviceName(device_name);
|
||||
|
||||
CefSize physical_size_device_units;
|
||||
CefRect printable_area_device_units;
|
||||
int dpi = gtk_print_settings_get_resolution(settings);
|
||||
if (dpi) {
|
||||
// Initialize page_setup_device_units_.
|
||||
physical_size_device_units.Set(
|
||||
gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH) * dpi,
|
||||
gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH) * dpi);
|
||||
printable_area_device_units.Set(
|
||||
gtk_page_setup_get_left_margin(page_setup, GTK_UNIT_INCH) * dpi,
|
||||
gtk_page_setup_get_top_margin(page_setup, GTK_UNIT_INCH) * dpi,
|
||||
gtk_page_setup_get_page_width(page_setup, GTK_UNIT_INCH) * dpi,
|
||||
gtk_page_setup_get_page_height(page_setup, GTK_UNIT_INCH) * dpi);
|
||||
} else {
|
||||
// Use default values if we cannot get valid values from the print dialog.
|
||||
dpi = kPixelsPerInch;
|
||||
double page_width_in_pixel = kLetterWidthInch * dpi;
|
||||
double page_height_in_pixel = kLetterHeightInch * dpi;
|
||||
physical_size_device_units.Set(
|
||||
static_cast<int>(page_width_in_pixel),
|
||||
static_cast<int>(page_height_in_pixel));
|
||||
printable_area_device_units.Set(
|
||||
static_cast<int>(kLeftMarginInInch * dpi),
|
||||
static_cast<int>(kTopMarginInInch * dpi),
|
||||
page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi,
|
||||
page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi);
|
||||
}
|
||||
|
||||
print_settings->SetDPI(dpi);
|
||||
|
||||
// Note: With the normal GTK print dialog, when the user selects the landscape
|
||||
// orientation, all that does is change the paper size. Which seems to be
|
||||
// enough to render the right output and send it to the printer.
|
||||
// The orientation value stays as portrait and does not actually affect
|
||||
// printing.
|
||||
// Thus this is only useful in print preview mode, where we manually set the
|
||||
// orientation and change the paper size ourselves.
|
||||
GtkPageOrientation orientation = gtk_print_settings_get_orientation(settings);
|
||||
// Set before SetPrinterPrintableArea to make it flip area if necessary.
|
||||
print_settings->SetOrientation(orientation == GTK_PAGE_ORIENTATION_LANDSCAPE);
|
||||
print_settings->SetPrinterPrintableArea(physical_size_device_units,
|
||||
printable_area_device_units,
|
||||
true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
ClientPrintHandlerGtk::ClientPrintHandlerGtk()
|
||||
: dialog_(NULL),
|
||||
gtk_settings_(NULL),
|
||||
page_setup_(NULL),
|
||||
printer_(NULL) {
|
||||
}
|
||||
|
||||
void ClientPrintHandlerGtk::OnPrintSettings(
|
||||
CefRefPtr<CefPrintSettings> settings,
|
||||
bool get_defaults) {
|
||||
if (get_defaults) {
|
||||
DCHECK(!page_setup_);
|
||||
DCHECK(!printer_);
|
||||
|
||||
// |gtk_settings_| is a new copy.
|
||||
gtk_settings_ =
|
||||
gtk_print_settings_copy(GetLastUsedSettings()->settings());
|
||||
page_setup_ = gtk_page_setup_new();
|
||||
} else {
|
||||
if (!gtk_settings_) {
|
||||
gtk_settings_ =
|
||||
gtk_print_settings_copy(GetLastUsedSettings()->settings());
|
||||
}
|
||||
|
||||
GtkPrinterList* printer_list = new GtkPrinterList;
|
||||
printer_ = printer_list->GetPrinterWithName(settings->GetDeviceName());
|
||||
if (printer_) {
|
||||
g_object_ref(printer_);
|
||||
gtk_print_settings_set_printer(gtk_settings_,
|
||||
gtk_printer_get_name(printer_));
|
||||
if (!page_setup_) {
|
||||
page_setup_ = gtk_printer_get_default_page_size(printer_);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_print_settings_set_n_copies(gtk_settings_, settings->GetCopies());
|
||||
gtk_print_settings_set_collate(gtk_settings_, settings->WillCollate());
|
||||
|
||||
std::string color_value;
|
||||
std::string color_setting_name;
|
||||
GetColorModelForMode(settings->GetColorModel(), &color_setting_name,
|
||||
&color_value);
|
||||
gtk_print_settings_set(gtk_settings_, color_setting_name.c_str(),
|
||||
color_value.c_str());
|
||||
|
||||
if (settings->GetDuplexMode() != DUPLEX_MODE_UNKNOWN) {
|
||||
const char* cups_duplex_mode = NULL;
|
||||
switch (settings->GetDuplexMode()) {
|
||||
case DUPLEX_MODE_LONG_EDGE:
|
||||
cups_duplex_mode = kDuplexNoTumble;
|
||||
break;
|
||||
case DUPLEX_MODE_SHORT_EDGE:
|
||||
cups_duplex_mode = kDuplexTumble;
|
||||
break;
|
||||
case DUPLEX_MODE_SIMPLEX:
|
||||
cups_duplex_mode = kDuplexNone;
|
||||
break;
|
||||
default: // UNKNOWN_DUPLEX_MODE
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode);
|
||||
}
|
||||
|
||||
if (!page_setup_)
|
||||
page_setup_ = gtk_page_setup_new();
|
||||
|
||||
gtk_print_settings_set_orientation(
|
||||
gtk_settings_,
|
||||
settings->IsLandscape() ? GTK_PAGE_ORIENTATION_LANDSCAPE :
|
||||
GTK_PAGE_ORIENTATION_PORTRAIT);
|
||||
|
||||
delete printer_list;
|
||||
}
|
||||
|
||||
InitPrintSettings(gtk_settings_, page_setup_, settings);
|
||||
}
|
||||
|
||||
bool ClientPrintHandlerGtk::OnPrintDialog(
|
||||
bool has_selection,
|
||||
CefRefPtr<CefPrintDialogCallback> callback) {
|
||||
dialog_callback_ = callback;
|
||||
|
||||
// TODO(cef): Identify the correct parent window.
|
||||
GtkWindow* parent = NULL;
|
||||
// TODO(estade): We need a window title here.
|
||||
dialog_ = gtk_print_unix_dialog_new(NULL, parent);
|
||||
g_signal_connect(dialog_, "delete-event",
|
||||
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
||||
|
||||
|
||||
// Set modal so user cannot focus the same tab and press print again.
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
|
||||
|
||||
// Since we only generate PDF, only show printers that support PDF.
|
||||
// TODO(thestig) Add more capabilities to support?
|
||||
GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>(
|
||||
GTK_PRINT_CAPABILITY_GENERATE_PDF |
|
||||
GTK_PRINT_CAPABILITY_PAGE_SET |
|
||||
GTK_PRINT_CAPABILITY_COPIES |
|
||||
GTK_PRINT_CAPABILITY_COLLATE |
|
||||
GTK_PRINT_CAPABILITY_REVERSE);
|
||||
gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_),
|
||||
cap);
|
||||
gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_),
|
||||
TRUE);
|
||||
gtk_print_unix_dialog_set_support_selection(GTK_PRINT_UNIX_DIALOG(dialog_),
|
||||
TRUE);
|
||||
gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_),
|
||||
has_selection);
|
||||
gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_),
|
||||
gtk_settings_);
|
||||
g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk),
|
||||
this);
|
||||
gtk_widget_show(dialog_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientPrintHandlerGtk::OnPrintJob(
|
||||
const CefString& document_name,
|
||||
const CefString& pdf_file_path,
|
||||
CefRefPtr<CefPrintJobCallback> callback) {
|
||||
// If |printer_| is NULL then somehow the GTK printer list changed out under
|
||||
// us. In which case, just bail out.
|
||||
if (!printer_)
|
||||
return false;
|
||||
|
||||
job_callback_ = callback;
|
||||
|
||||
// Save the settings for next time.
|
||||
GetLastUsedSettings()->SetLastUsedSettings(gtk_settings_);
|
||||
|
||||
GtkPrintJob* print_job = gtk_print_job_new(
|
||||
document_name.ToString().c_str(),
|
||||
printer_,
|
||||
gtk_settings_,
|
||||
page_setup_);
|
||||
gtk_print_job_set_source_file(print_job,
|
||||
pdf_file_path.ToString().c_str(),
|
||||
NULL);
|
||||
gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientPrintHandlerGtk::OnPrintReset() {
|
||||
if (dialog_) {
|
||||
gtk_widget_destroy(dialog_);
|
||||
dialog_ = NULL;
|
||||
}
|
||||
if (gtk_settings_) {
|
||||
g_object_unref(gtk_settings_);
|
||||
gtk_settings_ = NULL;
|
||||
}
|
||||
if (page_setup_) {
|
||||
g_object_unref(page_setup_);
|
||||
page_setup_ = NULL;
|
||||
}
|
||||
if (printer_) {
|
||||
g_object_unref(printer_);
|
||||
printer_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) {
|
||||
GtkPageSetup* page_setup = gtk_page_setup_new();
|
||||
|
||||
float width = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH);
|
||||
float height = gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH);
|
||||
|
||||
g_object_unref(page_setup);
|
||||
|
||||
return CefSize(width * device_units_per_inch, height * device_units_per_inch);
|
||||
}
|
||||
|
||||
void ClientPrintHandlerGtk::OnDialogResponse(GtkDialog *dialog,
|
||||
gint response_id) {
|
||||
int num_matched_handlers = g_signal_handlers_disconnect_by_func(
|
||||
dialog_, reinterpret_cast<gpointer>(&OnDialogResponseThunk), this);
|
||||
DCHECK_EQ(1, num_matched_handlers);
|
||||
|
||||
gtk_widget_hide(dialog_);
|
||||
|
||||
switch (response_id) {
|
||||
case GTK_RESPONSE_OK: {
|
||||
if (gtk_settings_)
|
||||
g_object_unref(gtk_settings_);
|
||||
gtk_settings_ = gtk_print_unix_dialog_get_settings(
|
||||
GTK_PRINT_UNIX_DIALOG(dialog_));
|
||||
|
||||
if (printer_)
|
||||
g_object_unref(printer_);
|
||||
printer_ = gtk_print_unix_dialog_get_selected_printer(
|
||||
GTK_PRINT_UNIX_DIALOG(dialog_));
|
||||
g_object_ref(printer_);
|
||||
|
||||
if (page_setup_)
|
||||
g_object_unref(page_setup_);
|
||||
page_setup_ = gtk_print_unix_dialog_get_page_setup(
|
||||
GTK_PRINT_UNIX_DIALOG(dialog_));
|
||||
g_object_ref(page_setup_);
|
||||
|
||||
// Handle page ranges.
|
||||
CefPrintSettings::PageRangeList ranges_vector;
|
||||
gint num_ranges;
|
||||
bool print_selection_only = false;
|
||||
switch (gtk_print_settings_get_print_pages(gtk_settings_)) {
|
||||
case GTK_PRINT_PAGES_RANGES: {
|
||||
GtkPageRange* gtk_range =
|
||||
gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges);
|
||||
if (gtk_range) {
|
||||
for (int i = 0; i < num_ranges; ++i) {
|
||||
ranges_vector.push_back(
|
||||
CefPageRange(gtk_range[i].start, gtk_range[i].end));
|
||||
}
|
||||
g_free(gtk_range);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GTK_PRINT_PAGES_SELECTION:
|
||||
print_selection_only = true;
|
||||
break;
|
||||
case GTK_PRINT_PAGES_ALL:
|
||||
// Leave |ranges_vector| empty to indicate print all pages.
|
||||
break;
|
||||
case GTK_PRINT_PAGES_CURRENT:
|
||||
default:
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
|
||||
CefRefPtr<CefPrintSettings> settings = CefPrintSettings::Create();
|
||||
settings->SetPageRanges(ranges_vector);
|
||||
settings->SetSelectionOnly(print_selection_only);
|
||||
InitPrintSettings(gtk_settings_, page_setup_, settings);
|
||||
dialog_callback_->Continue(settings);
|
||||
dialog_callback_ = NULL;
|
||||
return;
|
||||
}
|
||||
case GTK_RESPONSE_DELETE_EVENT: // Fall through.
|
||||
case GTK_RESPONSE_CANCEL: {
|
||||
dialog_callback_->Cancel();
|
||||
dialog_callback_ = NULL;
|
||||
return;
|
||||
}
|
||||
case GTK_RESPONSE_APPLY:
|
||||
default: {
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientPrintHandlerGtk::OnJobCompleted(GtkPrintJob* print_job,
|
||||
GError* error) {
|
||||
job_callback_->Continue();
|
||||
job_callback_ = NULL;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
||||
// Portions Copyright (c) 2012 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkunixprint.h>
|
||||
|
||||
#include "include/cef_print_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class ClientPrintHandlerGtk : public CefPrintHandler {
|
||||
public:
|
||||
ClientPrintHandlerGtk();
|
||||
|
||||
// CefPrintHandler methods.
|
||||
void OnPrintSettings(CefRefPtr<CefPrintSettings> settings,
|
||||
bool get_defaults) OVERRIDE;
|
||||
bool OnPrintDialog(
|
||||
bool has_selection,
|
||||
CefRefPtr<CefPrintDialogCallback> callback) OVERRIDE;
|
||||
bool OnPrintJob(const CefString& document_name,
|
||||
const CefString& pdf_file_path,
|
||||
CefRefPtr<CefPrintJobCallback> callback) OVERRIDE;
|
||||
void OnPrintReset() OVERRIDE;
|
||||
CefSize GetPdfPaperSize(int device_units_per_inch) OVERRIDE;
|
||||
|
||||
private:
|
||||
void OnDialogResponse(GtkDialog *dialog,
|
||||
gint response_id);
|
||||
void OnJobCompleted(GtkPrintJob* print_job,
|
||||
GError* error);
|
||||
|
||||
static void OnDialogResponseThunk(GtkDialog *dialog,
|
||||
gint response_id,
|
||||
ClientPrintHandlerGtk* handler) {
|
||||
handler->OnDialogResponse(dialog, response_id);
|
||||
}
|
||||
static void OnJobCompletedThunk(GtkPrintJob* print_job,
|
||||
void* handler,
|
||||
GError* error) {
|
||||
static_cast<ClientPrintHandlerGtk*>(handler)->
|
||||
OnJobCompleted(print_job, error);
|
||||
}
|
||||
|
||||
// Print dialog settings. ClientPrintHandlerGtk owns |dialog_| and holds
|
||||
// references to the other objects.
|
||||
GtkWidget* dialog_;
|
||||
GtkPrintSettings* gtk_settings_;
|
||||
GtkPageSetup* page_setup_;
|
||||
GtkPrinter* printer_;
|
||||
|
||||
CefRefPtr<CefPrintDialogCallback> dialog_callback_;
|
||||
CefRefPtr<CefPrintJobCallback> job_callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientPrintHandlerGtk);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientPrintHandlerGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_
|
||||
@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2013 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.
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by cefclient.rc
|
||||
//
|
||||
#define BINARY 256
|
||||
#define IDC_MYICON 2
|
||||
#define IDD_CEFCLIENT_DIALOG 102
|
||||
#define IDS_APP_TITLE 103
|
||||
#define IDD_ABOUTBOX 103
|
||||
#define IDM_ABOUT 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDI_CEFCLIENT 107
|
||||
#define IDI_SMALL 108
|
||||
#define IDC_CEFCLIENT 109
|
||||
#define IDS_OSR_WIDGET_CLASS 110
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDC_NAV_BACK 200
|
||||
#define IDC_NAV_FORWARD 201
|
||||
#define IDC_NAV_RELOAD 202
|
||||
#define IDC_NAV_STOP 203
|
||||
#define ID_QUIT 32500
|
||||
#define ID_FIND 32501
|
||||
#define ID_TESTS_FIRST 32700
|
||||
#define ID_TESTS_GETSOURCE 32700
|
||||
#define ID_TESTS_GETTEXT 32701
|
||||
#define ID_TESTS_OTHER_TESTS 32702
|
||||
#define ID_TESTS_PLUGIN_INFO 32703
|
||||
#define ID_TESTS_WINDOW_NEW 32704
|
||||
#define ID_TESTS_WINDOW_POPUP 32705
|
||||
#define ID_TESTS_PRINT 32706
|
||||
#define ID_TESTS_REQUEST 32707
|
||||
#define ID_TESTS_TRACING_BEGIN 32708
|
||||
#define ID_TESTS_TRACING_END 32709
|
||||
#define ID_TESTS_ZOOM_IN 32710
|
||||
#define ID_TESTS_ZOOM_OUT 32711
|
||||
#define ID_TESTS_ZOOM_RESET 32712
|
||||
#define ID_TESTS_OSR_FPS 32713
|
||||
#define ID_TESTS_OSR_DSF 32714
|
||||
#define ID_TESTS_PRINT_TO_PDF 32715
|
||||
#define ID_TESTS_LAST 32715
|
||||
#define IDC_STATIC -1
|
||||
#define IDS_BINDING_HTML 1000
|
||||
#define IDS_DIALOGS_HTML 1001
|
||||
#define IDS_LOCALSTORAGE_HTML 1002
|
||||
#define IDS_LOGO_PNG 1003
|
||||
#define IDS_OSRTEST_HTML 1004
|
||||
#define IDS_OTHER_TESTS_HTML 1005
|
||||
#define IDS_PDF_HTML 1006
|
||||
#define IDS_PDF_PDF 1007
|
||||
#define IDS_PERFORMANCE_HTML 1008
|
||||
#define IDS_PERFORMANCE2_HTML 1009
|
||||
#define IDS_TRANSPARENCY_HTML 1010
|
||||
#define IDS_URLREQUEST_HTML 1011
|
||||
#define IDS_WINDOW_HTML 1012
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1013
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 130
|
||||
#define _APS_NEXT_COMMAND_VALUE 32774
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 111
|
||||
#endif
|
||||
#endif
|
||||
@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2013 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 CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "include/cef_stream.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "include/wrapper/cef_resource_manager.h"
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
// Returns the directory containing resource files.
|
||||
bool GetResourceDir(std::string& dir);
|
||||
#endif
|
||||
|
||||
// Retrieve a resource as a string.
|
||||
bool LoadBinaryResource(const char* resource_name, std::string& resource_data);
|
||||
|
||||
// Retrieve a resource as a steam reader.
|
||||
CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Create a new provider for loading binary resources.
|
||||
CefResourceManager::Provider* CreateBinaryResourceProvider(
|
||||
const std::string& url_path);
|
||||
#endif
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_
|
||||
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2011 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 "cefclient/browser/resource_util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace client {
|
||||
|
||||
bool GetResourceDir(std::string& dir) {
|
||||
char buff[1024];
|
||||
|
||||
// Retrieve the executable path.
|
||||
ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
|
||||
if (len == -1)
|
||||
return false;
|
||||
|
||||
buff[len] = 0;
|
||||
|
||||
// Remove the executable name from the path.
|
||||
char* pos = strrchr(buff, '/');
|
||||
if (!pos)
|
||||
return false;
|
||||
|
||||
// Add "files" to the path.
|
||||
strcpy(pos+1, "files"); // NOLINT(runtime/printf)
|
||||
dir = std::string(buff);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2013 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 "cefclient/browser/resource_util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
bool FileExists(const char* path) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (f) {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadFileToString(const char* path, std::string& data) {
|
||||
// Implementation adapted from base/file_util.cc
|
||||
FILE* file = fopen(path, "rb");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
char buf[1 << 16];
|
||||
size_t len;
|
||||
while ((len = fread(buf, 1, sizeof(buf), file)) > 0)
|
||||
data.append(buf, len);
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool LoadBinaryResource(const char* resource_name, std::string& resource_data) {
|
||||
std::string path;
|
||||
if (!GetResourceDir(path))
|
||||
return false;
|
||||
|
||||
path.append("/");
|
||||
path.append(resource_name);
|
||||
|
||||
return ReadFileToString(path.c_str(), resource_data);
|
||||
}
|
||||
|
||||
CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
|
||||
std::string path;
|
||||
if (!GetResourceDir(path))
|
||||
return NULL;
|
||||
|
||||
path.append("/");
|
||||
path.append(resource_name);
|
||||
|
||||
if (!FileExists(path.c_str()))
|
||||
return NULL;
|
||||
|
||||
return CefStreamReader::CreateForFile(path);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/root_window.h"
|
||||
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/root_window_manager.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// static
|
||||
scoped_refptr<RootWindow> RootWindow::GetForBrowser(int browser_id) {
|
||||
return MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
|
||||
browser_id);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_ref_counted.h"
|
||||
#include "include/cef_browser.h"
|
||||
#include "cefclient/browser/client_types.h"
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents a top-level native window in the browser process. While references
|
||||
// to this object are thread-safe the methods must be called on the main thread
|
||||
// unless otherwise indicated.
|
||||
class RootWindow :
|
||||
public base::RefCountedThreadSafe<RootWindow, DeleteOnMainThread> {
|
||||
public:
|
||||
// This interface is implemented by the owner of the RootWindow. The methods
|
||||
// of this class will be called on the main thread.
|
||||
class Delegate {
|
||||
public:
|
||||
// Called to retrieve the CefRequestContext for browser. Only called for
|
||||
// non-popup browsers. May return NULL.
|
||||
virtual CefRefPtr<CefRequestContext> GetRequestContext(
|
||||
RootWindow* root_window) = 0;
|
||||
|
||||
// Called to execute a test. See resource.h for |test_id| values.
|
||||
virtual void OnTest(RootWindow* root_window, int test_id) = 0;
|
||||
|
||||
// Called to exit the application.
|
||||
virtual void OnExit(RootWindow* root_window) = 0;
|
||||
|
||||
// Called when the RootWindow has been destroyed.
|
||||
virtual void OnRootWindowDestroyed(RootWindow* root_window) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
|
||||
// Create a new RootWindow object. This method may be called on any thread.
|
||||
// Use RootWindowManager::CreateRootWindow() or CreateRootWindowAsPopup()
|
||||
// instead of calling this method directly.
|
||||
static scoped_refptr<RootWindow> Create();
|
||||
|
||||
// Returns the RootWindow associated with the specified |browser_id|. Must be
|
||||
// called on the main thread.
|
||||
static scoped_refptr<RootWindow> GetForBrowser(int browser_id);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Returns the RootWindow associated with the specified |window|. Must be
|
||||
// called on the main thread.
|
||||
static scoped_refptr<RootWindow> GetForNSWindow(NSWindow* window);
|
||||
#endif
|
||||
|
||||
// Initialize as a normal window. This will create and show a native window
|
||||
// hosting a single browser instance. This method may be called on any thread.
|
||||
// |delegate| must be non-NULL and outlive this object.
|
||||
// Use RootWindowManager::CreateRootWindow() instead of calling this method
|
||||
// directly.
|
||||
virtual void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) = 0;
|
||||
|
||||
// Initialize as a popup window. This is used to attach a new native window to
|
||||
// a single browser instance that will be created later. The native window
|
||||
// will be created and shown once the browser is available. This method may be
|
||||
// called on any thread. |delegate| must be non-NULL and outlive this object.
|
||||
// Use RootWindowManager::CreateRootWindowAsPopup() instead of calling this
|
||||
// method directly.
|
||||
virtual void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) = 0;
|
||||
|
||||
enum ShowMode {
|
||||
ShowNormal,
|
||||
ShowMinimized,
|
||||
ShowMaximized,
|
||||
};
|
||||
|
||||
// Show the window.
|
||||
virtual void Show(ShowMode mode) = 0;
|
||||
|
||||
// Hide the window.
|
||||
virtual void Hide() = 0;
|
||||
|
||||
// Set the window bounds in screen coordinates.
|
||||
virtual void SetBounds(int x, int y, size_t width, size_t height) = 0;
|
||||
|
||||
// Close the window. If |force| is true onunload handlers will not be
|
||||
// executed.
|
||||
virtual void Close(bool force) = 0;
|
||||
|
||||
// Set the device scale factor. Only used in combination with off-screen
|
||||
// rendering.
|
||||
virtual void SetDeviceScaleFactor(float device_scale_factor) = 0;
|
||||
|
||||
// Returns the device scale factor. Only used in combination with off-screen
|
||||
// rendering.
|
||||
virtual float GetDeviceScaleFactor() const = 0;
|
||||
|
||||
// Returns the browser that this window contains, if any.
|
||||
virtual CefRefPtr<CefBrowser> GetBrowser() const = 0;
|
||||
|
||||
// Returns the native handle for this window, if any.
|
||||
virtual ClientWindowHandle GetWindowHandle() const = 0;
|
||||
|
||||
protected:
|
||||
// Allow deletion via scoped_refptr only.
|
||||
friend struct DeleteOnMainThread;
|
||||
friend class base::RefCountedThreadSafe<RootWindow, DeleteOnMainThread>;
|
||||
|
||||
virtual ~RootWindow() {}
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
|
||||
@ -0,0 +1,665 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/root_window_gtk.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#undef Success // Definition conflicts with cef_message_router.h
|
||||
#undef RootWindow // Definition conflicts with root_window.h
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/cef_app.h"
|
||||
#include "cefclient/browser/browser_window_osr_gtk.h"
|
||||
#include "cefclient/browser/browser_window_std_gtk.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
#include "cefclient/browser/resource.h"
|
||||
#include "cefclient/browser/temp_window.h"
|
||||
#include "cefclient/browser/window_test.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kMenuIdKey[] = "menu_id";
|
||||
|
||||
bool IsWindowMaximized(GtkWindow* window) {
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||
gint state = gdk_window_get_state(gdk_window);
|
||||
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
||||
}
|
||||
|
||||
void MinimizeWindow(GtkWindow* window) {
|
||||
// Unmaximize the window before minimizing so restore behaves correctly.
|
||||
if (IsWindowMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
|
||||
gtk_window_iconify(window);
|
||||
}
|
||||
|
||||
void MaximizeWindow(GtkWindow* window) {
|
||||
gtk_window_maximize(window);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RootWindowGtk::RootWindowGtk()
|
||||
: delegate_(NULL),
|
||||
with_controls_(false),
|
||||
with_osr_(false),
|
||||
is_popup_(false),
|
||||
initialized_(false),
|
||||
window_(NULL),
|
||||
back_button_(NULL),
|
||||
forward_button_(NULL),
|
||||
reload_button_(NULL),
|
||||
stop_button_(NULL),
|
||||
url_entry_(NULL),
|
||||
toolbar_height_(0),
|
||||
menubar_height_(0),
|
||||
force_close_(false),
|
||||
window_destroyed_(false),
|
||||
browser_destroyed_(false) {
|
||||
}
|
||||
|
||||
RootWindowGtk::~RootWindowGtk() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// The window and browser should already have been destroyed.
|
||||
DCHECK(window_destroyed_);
|
||||
DCHECK(browser_destroyed_);
|
||||
}
|
||||
|
||||
void RootWindowGtk::Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
with_osr_ = with_osr;
|
||||
start_rect_ = bounds;
|
||||
|
||||
CreateBrowserWindow(url);
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
// Create the native root window on the main thread.
|
||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||
CreateRootWindow(settings);
|
||||
} else {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::CreateRootWindow, this, settings));
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(!initialized_);
|
||||
|
||||
delegate_ = delegate;
|
||||
with_controls_ = with_controls;
|
||||
with_osr_ = with_osr;
|
||||
is_popup_ = true;
|
||||
|
||||
if (popupFeatures.xSet)
|
||||
start_rect_.x = popupFeatures.x;
|
||||
if (popupFeatures.ySet)
|
||||
start_rect_.y = popupFeatures.y;
|
||||
if (popupFeatures.widthSet)
|
||||
start_rect_.width = popupFeatures.width;
|
||||
if (popupFeatures.heightSet)
|
||||
start_rect_.height = popupFeatures.height;
|
||||
|
||||
CreateBrowserWindow(std::string());
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
// The new popup is initially parented to a temporary window. The native root
|
||||
// window will be created after the browser is created and the popup window
|
||||
// will be re-parented to it at that time.
|
||||
browser_window_->GetPopupConfig(TempWindow::GetWindowHandle(),
|
||||
windowInfo, client, settings);
|
||||
}
|
||||
|
||||
void RootWindowGtk::Show(ShowMode mode) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
// Show the GTK window.
|
||||
gtk_widget_show_all(window_);
|
||||
|
||||
if (mode == ShowMinimized)
|
||||
MinimizeWindow(GTK_WINDOW(window_));
|
||||
else if (mode == ShowMaximized)
|
||||
MaximizeWindow(GTK_WINDOW(window_));
|
||||
}
|
||||
|
||||
void RootWindowGtk::Hide() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (window_)
|
||||
gtk_widget_hide(window_);
|
||||
}
|
||||
|
||||
void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
GtkWindow* window = GTK_WINDOW(window_);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
||||
|
||||
// Make sure the window isn't minimized or maximized.
|
||||
if (IsWindowMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
else
|
||||
gtk_window_present(window);
|
||||
|
||||
// Retrieve information about the display that contains the window.
|
||||
GdkScreen* screen = gdk_screen_get_default();
|
||||
const gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
|
||||
GdkRectangle rect;
|
||||
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
||||
|
||||
gdk_window_move_resize(gdk_window, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
|
||||
void RootWindowGtk::Close(bool force) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (window_) {
|
||||
force_close_ = force;
|
||||
gtk_widget_destroy(window_);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
||||
}
|
||||
|
||||
float RootWindowGtk::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
return browser_window_->GetDeviceScaleFactor();
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_window_)
|
||||
return browser_window_->GetBrowser();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClientWindowHandle RootWindowGtk::GetWindowHandle() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
return window_;
|
||||
}
|
||||
|
||||
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
|
||||
if (with_osr_) {
|
||||
OsrRenderer::Settings settings;
|
||||
MainContext::Get()->PopulateOsrSettings(&settings);
|
||||
browser_window_.reset(new BrowserWindowOsrGtk(this, startup_url, settings));
|
||||
} else {
|
||||
browser_window_.reset(new BrowserWindowStdGtk(this, startup_url));
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!window_);
|
||||
|
||||
// TODO(port): If no x,y position is specified the window will always appear
|
||||
// in the upper-left corner. Maybe there's a better default place to put it?
|
||||
int x = start_rect_.x;
|
||||
int y = start_rect_.y;
|
||||
int width, height;
|
||||
if (start_rect_.IsEmpty()) {
|
||||
// TODO(port): Also, maybe there's a better way to choose the default size.
|
||||
width = 800;
|
||||
height = 600;
|
||||
} else {
|
||||
width = start_rect_.width;
|
||||
height = start_rect_.height;
|
||||
}
|
||||
|
||||
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
|
||||
g_signal_connect(G_OBJECT(window_), "focus-in-event",
|
||||
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
|
||||
g_signal_connect(G_OBJECT(window_), "window-state-event",
|
||||
G_CALLBACK(&RootWindowGtk::WindowState), this);
|
||||
g_signal_connect(G_OBJECT(window_), "configure-event",
|
||||
G_CALLBACK(&RootWindowGtk::WindowConfigure), this);
|
||||
g_signal_connect(G_OBJECT(window_), "destroy",
|
||||
G_CALLBACK(&RootWindowGtk::WindowDestroy), this);
|
||||
g_signal_connect(G_OBJECT(window_), "delete_event",
|
||||
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
|
||||
|
||||
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
||||
GdkColor color = {0};
|
||||
color.red = CefColorGetR(background_color) * 65535 / 255;
|
||||
color.green = CefColorGetG(background_color) * 65535 / 255;
|
||||
color.blue = CefColorGetB(background_color) * 65535 / 255;
|
||||
gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &color);
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
|
||||
g_signal_connect(vbox, "size-allocate",
|
||||
G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this);
|
||||
gtk_container_add(GTK_CONTAINER(window_), vbox);
|
||||
|
||||
if (with_controls_) {
|
||||
GtkWidget* menu_bar = CreateMenuBar();
|
||||
g_signal_connect(menu_bar, "size-allocate",
|
||||
G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
|
||||
|
||||
GtkWidget* toolbar = gtk_toolbar_new();
|
||||
// Turn off the labels on the toolbar buttons.
|
||||
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
|
||||
g_signal_connect(toolbar, "size-allocate",
|
||||
G_CALLBACK(&RootWindowGtk::ToolbarSizeAllocated), this);
|
||||
|
||||
back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
|
||||
g_signal_connect(back_button_, "clicked",
|
||||
G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
|
||||
|
||||
forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
|
||||
g_signal_connect(forward_button_, "clicked",
|
||||
G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
|
||||
|
||||
reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
|
||||
g_signal_connect(reload_button_, "clicked",
|
||||
G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
|
||||
|
||||
stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
|
||||
g_signal_connect(stop_button_, "clicked",
|
||||
G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
|
||||
|
||||
url_entry_ = gtk_entry_new();
|
||||
g_signal_connect(url_entry_, "activate",
|
||||
G_CALLBACK(&RootWindowGtk::URLEntryActivate), this);
|
||||
g_signal_connect(url_entry_, "button-press-event",
|
||||
G_CALLBACK(&RootWindowGtk::URLEntryButtonPress), this);
|
||||
|
||||
GtkToolItem* tool_item = gtk_tool_item_new();
|
||||
gtk_container_add(GTK_CONTAINER(tool_item), url_entry_);
|
||||
gtk_tool_item_set_expand(tool_item, TRUE);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
|
||||
}
|
||||
|
||||
// Realize (show) the GTK widget. This must be done before the browser is
|
||||
// created because the underlying X11 Window is required. |browser_bounds_|
|
||||
// will be set at this point based on the GTK *SizeAllocated signal callbacks.
|
||||
Show(ShowNormal);
|
||||
|
||||
// Most window managers ignore requests for initial window positions (instead
|
||||
// using a user-defined placement algorithm) and honor requests after the
|
||||
// window has already been shown.
|
||||
gtk_window_move(GTK_WINDOW(window_), x, y);
|
||||
|
||||
// Windowed browsers are parented to the X11 Window underlying the GtkWindow*
|
||||
// and must be sized manually. The OSR GTK widget, on the other hand, can be
|
||||
// added to the Vbox container for automatic layout-based sizing.
|
||||
GtkWidget* parent = with_osr_ ? vbox : window_;
|
||||
|
||||
if (!is_popup_) {
|
||||
// Create the browser window.
|
||||
browser_window_->CreateBrowser(parent, browser_bounds_, settings,
|
||||
delegate_->GetRequestContext(this));
|
||||
} else {
|
||||
// With popups we already have a browser window. Parent the browser window
|
||||
// to the root window and show it in the correct location.
|
||||
browser_window_->ShowPopup(parent, browser_bounds_.x, browser_bounds_.y,
|
||||
browser_bounds_.width, browser_bounds_.height);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// For popup browsers create the root window once the browser has been
|
||||
// created.
|
||||
if (is_popup_)
|
||||
CreateRootWindow(CefBrowserSettings());
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnBrowserWindowDestroyed() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
browser_window_.reset();
|
||||
|
||||
if (!window_destroyed_) {
|
||||
// The browser was destroyed first. This could be due to the use of
|
||||
// off-screen rendering or execution of JavaScript window.close().
|
||||
// Close the RootWindow.
|
||||
Close(true);
|
||||
}
|
||||
|
||||
browser_destroyed_ = true;
|
||||
NotifyDestroyedIfDone();
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetAddress(const std::string& url) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (url_entry_) {
|
||||
std::string urlStr(url);
|
||||
gtk_entry_set_text(GTK_ENTRY(url_entry_), urlStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetTitle(const std::string& title) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (window_) {
|
||||
std::string titleStr(title);
|
||||
gtk_window_set_title(GTK_WINDOW(window_), titleStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetFullscreen(bool fullscreen) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
if (browser) {
|
||||
if (fullscreen)
|
||||
window_test::Maximize(browser);
|
||||
else
|
||||
window_test::Restore(browser);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (with_controls_) {
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(stop_button_), isLoading);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(reload_button_), !isLoading);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(back_button_), canGoBack);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(forward_button_), canGoForward);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
// TODO(cef): Implement support for draggable regions on this platform.
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyDestroyedIfDone() {
|
||||
// Notify once both the window and the browser have been destroyed.
|
||||
if (window_destroyed_ && browser_destroyed_)
|
||||
delegate_->OnRootWindowDestroyed(this);
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
|
||||
GdkEventFocus* event,
|
||||
RootWindowGtk* self) {
|
||||
if (event->in && self->browser_window_.get()) {
|
||||
self->browser_window_->SetFocus(true);
|
||||
// Return true for a windowed browser so that focus is not passed to GTK.
|
||||
return self->with_osr_ ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::WindowState(GtkWidget* widget,
|
||||
GdkEventWindowState* event,
|
||||
RootWindowGtk* self) {
|
||||
// Called when the root window is iconified or restored. Hide the browser
|
||||
// window when the root window is iconified to reduce resource usage.
|
||||
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
|
||||
self->browser_window_.get()) {
|
||||
if (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)
|
||||
self->browser_window_->Hide();
|
||||
else
|
||||
self->browser_window_->Show();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self) {
|
||||
// Called when size, position or stack order changes.
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get()) {
|
||||
// Notify the browser of move/resize events so that:
|
||||
// - Popup windows are displayed in the correct location and dismissed
|
||||
// when the window moves.
|
||||
// - Drag&drop areas are updated accordingly.
|
||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::WindowDestroy(GtkWidget* widget, RootWindowGtk* self) {
|
||||
// Called when the root window is destroyed.
|
||||
self->window_destroyed_ = true;
|
||||
self->NotifyDestroyedIfDone();
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self) {
|
||||
// Called to query whether the root window should be closed.
|
||||
if (self->force_close_)
|
||||
return FALSE; // Allow the close.
|
||||
|
||||
if (self->browser_window_.get() && !self->browser_window_->IsClosing()) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser) {
|
||||
// Notify the browser window that we would like to close it. This
|
||||
// will result in a call to ClientHandler::DoClose() if the
|
||||
// JavaScript 'onbeforeunload' event handler allows it.
|
||||
browser->GetHost()->CloseBrowser(false);
|
||||
|
||||
// Cancel the close.
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the close.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self) {
|
||||
// Offset browser positioning by any controls that will appear in the client
|
||||
// area.
|
||||
const int ux_height = self->toolbar_height_ + self->menubar_height_;
|
||||
const int x = allocation->x;
|
||||
const int y = allocation->y + ux_height;
|
||||
const int width = allocation->width;
|
||||
const int height = allocation->height - ux_height;
|
||||
|
||||
// Size the browser window to match the GTK widget.
|
||||
self->browser_bounds_ = CefRect(x, y, width, height);
|
||||
if (self->browser_window_.get())
|
||||
self->browser_window_->SetBounds(x, y, width, height);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self) {
|
||||
self->menubar_height_ = allocation->height;
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
|
||||
RootWindowGtk* self) {
|
||||
// Retrieve the menu ID set in AddMenuEntry.
|
||||
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
|
||||
// Run the test.
|
||||
if (self->delegate_)
|
||||
self->delegate_->OnTest(self, id);
|
||||
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::ToolbarSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self) {
|
||||
self->toolbar_height_ = allocation->height;
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::BackButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->GoBack();
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->GoForward();
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::StopButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->StopLoad();
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->Reload();
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::URLEntryActivate(GtkEntry* entry,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get()) {
|
||||
const gchar* url = gtk_entry_get_text(entry);
|
||||
browser->GetMainFrame()->LoadURL(std::string(url).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
RootWindowGtk* self) {
|
||||
// Give focus to the GTK window. This is a work-around for bad focus-related
|
||||
// interaction between the root window managed by GTK and the browser managed
|
||||
// by X11.
|
||||
GtkWidget* window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(window);
|
||||
::Display* xdisplay = GDK_WINDOW_XDISPLAY(gdk_window);
|
||||
::Window xwindow = GDK_WINDOW_XID(gdk_window);
|
||||
XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget* RootWindowGtk::CreateMenuBar() {
|
||||
GtkWidget* menu_bar = gtk_menu_bar_new();
|
||||
|
||||
// Create the test menu.
|
||||
GtkWidget* test_menu = CreateMenu(menu_bar, "Tests");
|
||||
AddMenuEntry(test_menu, "Get Source", ID_TESTS_GETSOURCE);
|
||||
AddMenuEntry(test_menu, "Get Text", ID_TESTS_GETTEXT);
|
||||
AddMenuEntry(test_menu, "New Window", ID_TESTS_WINDOW_NEW);
|
||||
AddMenuEntry(test_menu, "Popup Window", ID_TESTS_WINDOW_POPUP);
|
||||
AddMenuEntry(test_menu, "Request", ID_TESTS_REQUEST);
|
||||
AddMenuEntry(test_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO);
|
||||
AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN);
|
||||
AddMenuEntry(test_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
|
||||
AddMenuEntry(test_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
|
||||
if (with_osr_) {
|
||||
AddMenuEntry(test_menu, "Set FPS", ID_TESTS_OSR_FPS);
|
||||
AddMenuEntry(test_menu, "Set Scale Factor", ID_TESTS_OSR_DSF);
|
||||
}
|
||||
AddMenuEntry(test_menu, "Begin Tracing", ID_TESTS_TRACING_BEGIN);
|
||||
AddMenuEntry(test_menu, "End Tracing", ID_TESTS_TRACING_END);
|
||||
AddMenuEntry(test_menu, "Print", ID_TESTS_PRINT);
|
||||
AddMenuEntry(test_menu, "Print to PDF", ID_TESTS_PRINT_TO_PDF);
|
||||
AddMenuEntry(test_menu, "Other Tests", ID_TESTS_OTHER_TESTS);
|
||||
|
||||
return menu_bar;
|
||||
}
|
||||
|
||||
GtkWidget* RootWindowGtk::CreateMenu(GtkWidget* menu_bar, const char* text) {
|
||||
GtkWidget* menu_widget = gtk_menu_new();
|
||||
GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
|
||||
return menu_widget;
|
||||
}
|
||||
|
||||
GtkWidget* RootWindowGtk::AddMenuEntry(GtkWidget* menu_widget,
|
||||
const char* text,
|
||||
int id) {
|
||||
GtkWidget* entry = gtk_menu_item_new_with_label(text);
|
||||
g_signal_connect(entry, "activate",
|
||||
G_CALLBACK(&RootWindowGtk::MenuItemActivated), this);
|
||||
|
||||
// Set the menu ID that will be retrieved in MenuItemActivated.
|
||||
g_object_set_data(G_OBJECT(entry), kMenuIdKey, GINT_TO_POINTER(id));
|
||||
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<RootWindow> RootWindow::Create() {
|
||||
return new RootWindowGtk();
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "cefclient/browser/browser_window.h"
|
||||
#include "cefclient/browser/root_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// GTK implementation of a top-level native window in the browser process.
|
||||
// The methods of this class must be called on the main thread unless otherwise
|
||||
// indicated.
|
||||
class RootWindowGtk : public RootWindow,
|
||||
public BrowserWindow::Delegate {
|
||||
public:
|
||||
// Constructor may be called on any thread.
|
||||
RootWindowGtk();
|
||||
~RootWindowGtk();
|
||||
|
||||
// RootWindow methods.
|
||||
void Init(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& rect,
|
||||
const CefBrowserSettings& settings,
|
||||
const std::string& url) OVERRIDE;
|
||||
void InitAsPopup(RootWindow::Delegate* delegate,
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) OVERRIDE;
|
||||
void Show(ShowMode mode) OVERRIDE;
|
||||
void Hide() OVERRIDE;
|
||||
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
|
||||
void Close(bool force) OVERRIDE;
|
||||
void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
|
||||
float GetDeviceScaleFactor() const OVERRIDE;
|
||||
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
|
||||
private:
|
||||
void CreateBrowserWindow(const std::string& startup_url);
|
||||
void CreateRootWindow(const CefBrowserSettings& settings);
|
||||
|
||||
// BrowserWindow::Delegate methods.
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBrowserWindowDestroyed() OVERRIDE;
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
void OnSetFullscreen(bool fullscreen) OVERRIDE;
|
||||
void OnSetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE;
|
||||
void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
|
||||
void NotifyDestroyedIfDone();
|
||||
|
||||
GtkWidget* CreateMenuBar();
|
||||
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
|
||||
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, int id);
|
||||
|
||||
// Signal handlers for the top-level GTK window.
|
||||
static gboolean WindowFocusIn(GtkWidget* widget,
|
||||
GdkEventFocus* event,
|
||||
RootWindowGtk* self);
|
||||
static gboolean WindowState(GtkWidget* widget,
|
||||
GdkEventWindowState* event,
|
||||
RootWindowGtk* self);
|
||||
static gboolean WindowConfigure(GtkWindow* window,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self);
|
||||
static void WindowDestroy(GtkWidget* widget, RootWindowGtk* self);
|
||||
static gboolean WindowDelete(GtkWidget* widget,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self);
|
||||
|
||||
// Signal handlers for the GTK Vbox containing all UX elements.
|
||||
static void VboxSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self);
|
||||
|
||||
// Signal handlers for the GTK menu bar.
|
||||
static void MenubarSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self);
|
||||
static gboolean MenuItemActivated(GtkWidget* widget,
|
||||
RootWindowGtk* self);
|
||||
|
||||
// Signal handlers for the GTK toolbar.
|
||||
static void ToolbarSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self);
|
||||
static void BackButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self);
|
||||
static void ForwardButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self);
|
||||
static void StopButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self);
|
||||
static void ReloadButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self);
|
||||
|
||||
// Signal handlers for the GTK URL entry field.
|
||||
static void URLEntryActivate(GtkEntry* entry,
|
||||
RootWindowGtk* self);
|
||||
static gboolean URLEntryButtonPress(GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
RootWindowGtk* self);
|
||||
|
||||
// After initialization all members are only accessed on the main thread.
|
||||
// Members set during initialization.
|
||||
RootWindow::Delegate* delegate_;
|
||||
bool with_controls_;
|
||||
bool with_osr_;
|
||||
bool is_popup_;
|
||||
CefRect start_rect_;
|
||||
scoped_ptr<BrowserWindow> browser_window_;
|
||||
bool initialized_;
|
||||
|
||||
// Main window.
|
||||
GtkWidget* window_;
|
||||
|
||||
// Buttons.
|
||||
GtkToolItem* back_button_;
|
||||
GtkToolItem* forward_button_;
|
||||
GtkToolItem* reload_button_;
|
||||
GtkToolItem* stop_button_;
|
||||
|
||||
// URL text field.
|
||||
GtkWidget* url_entry_;
|
||||
|
||||
// Height of UX controls that affect browser window placement.
|
||||
int toolbar_height_;
|
||||
int menubar_height_;
|
||||
|
||||
CefRect browser_bounds_;
|
||||
|
||||
bool force_close_;
|
||||
bool window_destroyed_;
|
||||
bool browser_destroyed_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_GTK_H_
|
||||
@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/root_window_manager.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
RootWindowManager::RootWindowManager(bool terminate_when_all_windows_closed)
|
||||
: terminate_when_all_windows_closed_(terminate_when_all_windows_closed) {
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
DCHECK(command_line.get());
|
||||
request_context_per_browser_ =
|
||||
command_line->HasSwitch(switches::kRequestContextPerBrowser);
|
||||
}
|
||||
|
||||
RootWindowManager::~RootWindowManager() {
|
||||
// All root windows should already have been destroyed.
|
||||
DCHECK(root_windows_.empty());
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const std::string& url) {
|
||||
CefBrowserSettings settings;
|
||||
MainContext::Get()->PopulateBrowserSettings(&settings);
|
||||
|
||||
scoped_refptr<RootWindow> root_window = RootWindow::Create();
|
||||
root_window->Init(this, with_controls, with_osr, bounds, settings,
|
||||
url.empty() ? MainContext::Get()->GetMainURL() : url);
|
||||
|
||||
// Store a reference to the root window on the main thread.
|
||||
OnRootWindowCreated(root_window);
|
||||
|
||||
return root_window;
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
MainContext::Get()->PopulateBrowserSettings(&settings);
|
||||
|
||||
scoped_refptr<RootWindow> root_window = RootWindow::Create();
|
||||
root_window->InitAsPopup(this, with_controls, with_osr,
|
||||
popupFeatures, windowInfo, client, settings);
|
||||
|
||||
// Store a reference to the root window on the main thread.
|
||||
OnRootWindowCreated(root_window);
|
||||
|
||||
return root_window;
|
||||
}
|
||||
|
||||
scoped_refptr<RootWindow> RootWindowManager::GetWindowForBrowser(
|
||||
int browser_id) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowSet::const_iterator it = root_windows_.begin();
|
||||
for (; it != root_windows_.end(); ++it) {
|
||||
CefRefPtr<CefBrowser> browser = (*it)->GetBrowser();
|
||||
if (browser.get() && browser->GetIdentifier() == browser_id)
|
||||
return *it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RootWindowManager::CloseAllWindows(bool force) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowManager::CloseAllWindows, base::Unretained(this),
|
||||
force));
|
||||
return;
|
||||
}
|
||||
|
||||
if (root_windows_.empty())
|
||||
return;
|
||||
|
||||
RootWindowSet::const_iterator it = root_windows_.begin();
|
||||
for (; it != root_windows_.end(); ++it)
|
||||
(*it)->Close(force);
|
||||
}
|
||||
|
||||
void RootWindowManager::OnRootWindowCreated(
|
||||
scoped_refptr<RootWindow> root_window) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowManager::OnRootWindowCreated,
|
||||
base::Unretained(this), root_window));
|
||||
return;
|
||||
}
|
||||
|
||||
root_windows_.insert(root_window);
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequestContext> RootWindowManager::GetRequestContext(
|
||||
RootWindow* root_window) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (request_context_per_browser_) {
|
||||
// Create a new request context for each browser.
|
||||
CefRequestContextSettings settings;
|
||||
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
if (command_line->HasSwitch(switches::kCachePath)) {
|
||||
// If a global cache path value is specified then give each browser a
|
||||
// unique cache path.
|
||||
std::stringstream ss;
|
||||
ss << command_line->GetSwitchValue(switches::kCachePath).ToString() <<
|
||||
time(NULL);
|
||||
CefString(&settings.cache_path) = ss.str();
|
||||
}
|
||||
|
||||
return CefRequestContext::CreateContext(settings, NULL);
|
||||
}
|
||||
|
||||
// All browsers will share the global request context.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RootWindowManager::OnTest(RootWindow* root_window, int test_id) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
test_runner::RunTest(root_window->GetBrowser(), test_id);
|
||||
}
|
||||
|
||||
void RootWindowManager::OnExit(RootWindow* root_window) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
CloseAllWindows(false);
|
||||
}
|
||||
|
||||
void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowSet::iterator it = root_windows_.find(root_window);
|
||||
DCHECK(it != root_windows_.end());
|
||||
if (it != root_windows_.end())
|
||||
root_windows_.erase(it);
|
||||
|
||||
if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
|
||||
// Quit the main message loop after all windows have closed.
|
||||
MainMessageLoop::Get()->Quit();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_command_line.h"
|
||||
#include "cefclient/browser/root_window.h"
|
||||
#include "cefclient/browser/temp_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Used to create/manage RootWindow instances. The methods of this class can be
|
||||
// called from any browser process thread unless otherwise indicated.
|
||||
class RootWindowManager : public RootWindow::Delegate {
|
||||
public:
|
||||
// If |terminate_when_all_windows_closed| is true quit the main message loop
|
||||
// after all windows have closed.
|
||||
explicit RootWindowManager(bool terminate_when_all_windows_closed);
|
||||
|
||||
// Create a new top-level native window that loads |url|.
|
||||
// If |with_controls| is true the window will show controls.
|
||||
// If |with_osr| is true the window will use off-screen rendering.
|
||||
// If |bounds| is empty the default window size and location will be used.
|
||||
// This method can be called from anywhere to create a new top-level window.
|
||||
scoped_refptr<RootWindow> CreateRootWindow(
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefRect& bounds,
|
||||
const std::string& url);
|
||||
|
||||
// Create a new native popup window.
|
||||
// If |with_controls| is true the window will show controls.
|
||||
// If |with_osr| is true the window will use off-screen rendering.
|
||||
// This method is called from ClientHandler::CreatePopupWindow() to
|
||||
// create a new popup or DevTools window.
|
||||
scoped_refptr<RootWindow> CreateRootWindowAsPopup(
|
||||
bool with_controls,
|
||||
bool with_osr,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings);
|
||||
|
||||
// Returns the RootWindow associated with the specified browser ID. Must be
|
||||
// called on the main thread.
|
||||
scoped_refptr<RootWindow> GetWindowForBrowser(int browser_id);
|
||||
|
||||
// Close all existing windows. If |force| is true onunload handlers will not
|
||||
// be executed.
|
||||
void CloseAllWindows(bool force);
|
||||
|
||||
private:
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<RootWindowManager>;
|
||||
|
||||
~RootWindowManager();
|
||||
|
||||
void OnRootWindowCreated(scoped_refptr<RootWindow> root_window);
|
||||
|
||||
// RootWindow::Delegate methods.
|
||||
CefRefPtr<CefRequestContext> GetRequestContext(
|
||||
RootWindow* root_window) OVERRIDE;
|
||||
void OnTest(RootWindow* root_window, int test_id) OVERRIDE;
|
||||
void OnExit(RootWindow* root_window) OVERRIDE;
|
||||
void OnRootWindowDestroyed(RootWindow* root_window) OVERRIDE;
|
||||
|
||||
const bool terminate_when_all_windows_closed_;
|
||||
bool request_context_per_browser_;
|
||||
|
||||
// Existing root windows. Only accessed on the main thread.
|
||||
typedef std::set<scoped_refptr<RootWindow> > RootWindowSet;
|
||||
RootWindowSet root_windows_;
|
||||
|
||||
// Singleton window used as the temporary parent for popup browsers.
|
||||
TempWindow temp_window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowManager);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_
|
||||
@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2012 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 "cefclient/browser/scheme_test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/cef_callback.h"
|
||||
#include "include/cef_frame.h"
|
||||
#include "include/cef_resource_handler.h"
|
||||
#include "include/cef_response.h"
|
||||
#include "include/cef_request.h"
|
||||
#include "include/cef_scheme.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "cefclient/browser/resource_util.h"
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client {
|
||||
namespace scheme_test {
|
||||
|
||||
namespace {
|
||||
|
||||
// Implementation of the schema handler for client:// requests.
|
||||
class ClientSchemeHandler : public CefResourceHandler {
|
||||
public:
|
||||
ClientSchemeHandler() : offset_(0) {}
|
||||
|
||||
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback)
|
||||
OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
bool handled = false;
|
||||
|
||||
std::string url = request->GetURL();
|
||||
if (strstr(url.c_str(), "handler.html") != NULL) {
|
||||
// Build the response html
|
||||
data_ = "<html><head><title>Client Scheme Handler</title></head>"
|
||||
"<body bgcolor=\"white\">"
|
||||
"This contents of this page page are served by the "
|
||||
"ClientSchemeHandler class handling the client:// protocol."
|
||||
"<br/>You should see an image:"
|
||||
"<br/><img src=\"client://tests/logo.png\"><pre>";
|
||||
|
||||
// Output a string representation of the request
|
||||
const std::string& dump = test_runner::DumpRequestContents(request);
|
||||
data_.append(dump);
|
||||
|
||||
data_.append("</pre><br/>Try the test form:"
|
||||
"<form method=\"POST\" action=\"handler.html\">"
|
||||
"<input type=\"text\" name=\"field1\">"
|
||||
"<input type=\"text\" name=\"field2\">"
|
||||
"<input type=\"submit\">"
|
||||
"</form></body></html>");
|
||||
|
||||
handled = true;
|
||||
|
||||
// Set the resulting mime type
|
||||
mime_type_ = "text/html";
|
||||
} else if (strstr(url.c_str(), "logo.png") != NULL) {
|
||||
// Load the response image
|
||||
if (LoadBinaryResource("logo.png", data_)) {
|
||||
handled = true;
|
||||
// Set the resulting mime type
|
||||
mime_type_ = "image/png";
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
// Indicate the headers are available.
|
||||
callback->Continue();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||
int64& response_length,
|
||||
CefString& redirectUrl) OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
DCHECK(!data_.empty());
|
||||
|
||||
response->SetMimeType(mime_type_);
|
||||
response->SetStatus(200);
|
||||
|
||||
// Set the resulting response length
|
||||
response_length = data_.length();
|
||||
}
|
||||
|
||||
virtual void Cancel() OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
}
|
||||
|
||||
virtual bool ReadResponse(void* data_out,
|
||||
int bytes_to_read,
|
||||
int& bytes_read,
|
||||
CefRefPtr<CefCallback> callback)
|
||||
OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
bool has_data = false;
|
||||
bytes_read = 0;
|
||||
|
||||
if (offset_ < data_.length()) {
|
||||
// Copy the next block of data into the buffer.
|
||||
int transfer_size =
|
||||
std::min(bytes_to_read, static_cast<int>(data_.length() - offset_));
|
||||
memcpy(data_out, data_.c_str() + offset_, transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
bytes_read = transfer_size;
|
||||
has_data = true;
|
||||
}
|
||||
|
||||
return has_data;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
std::string mime_type_;
|
||||
size_t offset_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
|
||||
};
|
||||
|
||||
// Implementation of the factory for for creating schema handlers.
|
||||
class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
||||
public:
|
||||
// Return a new scheme handler instance to handle the request.
|
||||
virtual CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request)
|
||||
OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
return new ClientSchemeHandler();
|
||||
}
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void RegisterSchemeHandlers() {
|
||||
CefRegisterSchemeHandlerFactory("client", "tests",
|
||||
new ClientSchemeHandlerFactory());
|
||||
}
|
||||
|
||||
} // namespace scheme_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,20 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_SCHEME_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_SCHEME_TEST_H_
|
||||
#pragma once
|
||||
|
||||
namespace client {
|
||||
namespace scheme_test {
|
||||
|
||||
// Create and register the custom scheme handler. See
|
||||
// common/scheme_handler_common.h for registration of the custom scheme
|
||||
// name/type which must occur in all processes. Called from test_runner.cc.
|
||||
void RegisterSchemeHandlers();
|
||||
|
||||
} // namespace scheme_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_SCHEME_TEST_H_
|
||||
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/client_types.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "cefclient/browser/temp_window_win.h"
|
||||
#elif defined(OS_LINUX)
|
||||
#include "cefclient/browser/temp_window_x11.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "cefclient/browser/temp_window_mac.h"
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef TempWindowWin TempWindow;
|
||||
#elif defined(OS_LINUX)
|
||||
typedef TempWindowX11 TempWindow;
|
||||
#elif defined(OS_MACOSX)
|
||||
typedef TempWindowMac TempWindow;
|
||||
#endif
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_H_
|
||||
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/temp_window_x11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/cef_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// Create the temp window.
|
||||
::Window CreateTempWindow() {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
::Window parent_xwindow = DefaultRootWindow(xdisplay);
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
memset(&swa, 0, sizeof(swa));
|
||||
swa.background_pixmap = None;
|
||||
swa.override_redirect = false;
|
||||
return XCreateWindow(
|
||||
xdisplay, parent_xwindow,
|
||||
0, 0, 1, 1, // size (1x1px)
|
||||
0, // border width
|
||||
CopyFromParent, // depth
|
||||
InputOutput,
|
||||
CopyFromParent, // visual
|
||||
CWBackPixmap | CWOverrideRedirect,
|
||||
&swa);
|
||||
}
|
||||
|
||||
// Close the temp window.
|
||||
void CloseTempWindow(::Window xwindow) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
XDestroyWindow(xdisplay, xwindow);
|
||||
}
|
||||
|
||||
TempWindowX11* g_temp_window = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
TempWindowX11::TempWindowX11()
|
||||
: xwindow_(kNullWindowHandle) {
|
||||
DCHECK(!g_temp_window);
|
||||
g_temp_window = this;
|
||||
|
||||
xwindow_ = CreateTempWindow();
|
||||
CHECK(xwindow_);
|
||||
}
|
||||
|
||||
TempWindowX11::~TempWindowX11() {
|
||||
g_temp_window = NULL;
|
||||
DCHECK(xwindow_);
|
||||
|
||||
CloseTempWindow(xwindow_);
|
||||
}
|
||||
|
||||
// static
|
||||
CefWindowHandle TempWindowX11::GetWindowHandle() {
|
||||
DCHECK(g_temp_window);
|
||||
return g_temp_window->xwindow_;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_X11_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_X11_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_base.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents a singleton hidden window that acts at temporary parent for
|
||||
// popup browsers.
|
||||
class TempWindowX11 {
|
||||
public:
|
||||
// Returns the singleton window handle.
|
||||
static CefWindowHandle GetWindowHandle();
|
||||
|
||||
private:
|
||||
// A single instance will be created/owned by RootWindowManager.
|
||||
friend class RootWindowManager;
|
||||
|
||||
TempWindowX11();
|
||||
~TempWindowX11();
|
||||
|
||||
CefWindowHandle xwindow_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TempWindowX11);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_X11_H_
|
||||
@ -0,0 +1,723 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/test_runner.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/cef_task.h"
|
||||
#include "include/cef_trace.h"
|
||||
#include "include/cef_web_plugin.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "cefclient/browser/binding_test.h"
|
||||
#include "cefclient/browser/dialog_test.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/resource.h"
|
||||
#include "cefclient/browser/resource_util.h"
|
||||
#include "cefclient/browser/root_window_manager.h"
|
||||
#include "cefclient/browser/scheme_test.h"
|
||||
#include "cefclient/browser/urlrequest_test.h"
|
||||
#include "cefclient/browser/window_test.h"
|
||||
|
||||
namespace client {
|
||||
namespace test_runner {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestOrigin[] = "http://tests/";
|
||||
|
||||
// Replace all instances of |from| with |to| in |str|.
|
||||
std::string StringReplace(const std::string& str, const std::string& from,
|
||||
const std::string& to) {
|
||||
std::string result = str;
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type from_len = from.length();
|
||||
std::string::size_type to_len = to.length();
|
||||
do {
|
||||
pos = result.find(from, pos);
|
||||
if (pos != std::string::npos) {
|
||||
result.replace(pos, from_len, to);
|
||||
pos += to_len;
|
||||
}
|
||||
} while (pos != std::string::npos);
|
||||
return result;
|
||||
}
|
||||
|
||||
void RunGetSourceTest(CefRefPtr<CefBrowser> browser) {
|
||||
class Visitor : public CefStringVisitor {
|
||||
public:
|
||||
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
||||
virtual void Visit(const CefString& string) OVERRIDE {
|
||||
std::string source = StringReplace(string, "<", "<");
|
||||
source = StringReplace(source, ">", ">");
|
||||
std::stringstream ss;
|
||||
ss << "<html><body bgcolor=\"white\">Source:<pre>" << source <<
|
||||
"</pre></body></html>";
|
||||
browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/getsource");
|
||||
}
|
||||
private:
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
IMPLEMENT_REFCOUNTING(Visitor);
|
||||
};
|
||||
|
||||
browser->GetMainFrame()->GetSource(new Visitor(browser));
|
||||
}
|
||||
|
||||
void RunGetTextTest(CefRefPtr<CefBrowser> browser) {
|
||||
class Visitor : public CefStringVisitor {
|
||||
public:
|
||||
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
||||
virtual void Visit(const CefString& string) OVERRIDE {
|
||||
std::string text = StringReplace(string, "<", "<");
|
||||
text = StringReplace(text, ">", ">");
|
||||
std::stringstream ss;
|
||||
ss << "<html><body bgcolor=\"white\">Text:<pre>" << text <<
|
||||
"</pre></body></html>";
|
||||
browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/gettext");
|
||||
}
|
||||
private:
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
IMPLEMENT_REFCOUNTING(Visitor);
|
||||
};
|
||||
|
||||
browser->GetMainFrame()->GetText(new Visitor(browser));
|
||||
}
|
||||
|
||||
void RunRequestTest(CefRefPtr<CefBrowser> browser) {
|
||||
// Create a new request
|
||||
CefRefPtr<CefRequest> request(CefRequest::Create());
|
||||
|
||||
// Set the request URL
|
||||
request->SetURL("http://tests/request");
|
||||
|
||||
// Add post data to the request. The correct method and content-
|
||||
// type headers will be set by CEF.
|
||||
CefRefPtr<CefPostDataElement> postDataElement(CefPostDataElement::Create());
|
||||
std::string data = "arg1=val1&arg2=val2";
|
||||
postDataElement->SetToBytes(data.length(), data.c_str());
|
||||
CefRefPtr<CefPostData> postData(CefPostData::Create());
|
||||
postData->AddElement(postDataElement);
|
||||
request->SetPostData(postData);
|
||||
|
||||
// Add a custom header
|
||||
CefRequest::HeaderMap headerMap;
|
||||
headerMap.insert(
|
||||
std::make_pair("X-My-Header", "My Header Value"));
|
||||
request->SetHeaderMap(headerMap);
|
||||
|
||||
// Load the request
|
||||
browser->GetMainFrame()->LoadRequest(request);
|
||||
}
|
||||
|
||||
void RunNewWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
true, // Show controls.
|
||||
browser->GetHost()->IsWindowRenderingDisabled(),
|
||||
CefRect(), // Use default system size.
|
||||
std::string()); // Use default URL.
|
||||
}
|
||||
|
||||
void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||
browser->GetMainFrame()->ExecuteJavaScript(
|
||||
"window.open('http://www.google.com');", "about:blank", 0);
|
||||
}
|
||||
|
||||
void RunPluginInfoTest(CefRefPtr<CefBrowser> browser) {
|
||||
class Visitor : public CefWebPluginInfoVisitor {
|
||||
public:
|
||||
explicit Visitor(CefRefPtr<CefBrowser> browser)
|
||||
: browser_(browser) {
|
||||
html_ = "<html><head><title>Plugin Info Test</title></head>"
|
||||
"<body bgcolor=\"white\">"
|
||||
"\n<b>Installed plugins:</b>";
|
||||
}
|
||||
~Visitor() {
|
||||
html_ += "\n</body></html>";
|
||||
|
||||
// Load the html in the browser.
|
||||
browser_->GetMainFrame()->LoadString(html_, "http://tests/plugin_info");
|
||||
}
|
||||
|
||||
virtual bool Visit(CefRefPtr<CefWebPluginInfo> info, int count, int total)
|
||||
OVERRIDE {
|
||||
html_ += "\n<br/><br/>Name: " + info->GetName().ToString() +
|
||||
"\n<br/>Description: " + info->GetDescription().ToString() +
|
||||
"\n<br/>Version: " + info->GetVersion().ToString() +
|
||||
"\n<br/>Path: " + info->GetPath().ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string html_;
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
IMPLEMENT_REFCOUNTING(Visitor);
|
||||
};
|
||||
|
||||
CefVisitWebPluginInfo(new Visitor(browser));
|
||||
}
|
||||
|
||||
void ModifyZoom(CefRefPtr<CefBrowser> browser, double delta) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&ModifyZoom, browser, delta));
|
||||
return;
|
||||
}
|
||||
|
||||
browser->GetHost()->SetZoomLevel(
|
||||
browser->GetHost()->GetZoomLevel() + delta);
|
||||
}
|
||||
|
||||
const char kPrompt[] = "Prompt.";
|
||||
const char kPromptFPS[] = "FPS";
|
||||
const char kPromptDSF[] = "DSF";
|
||||
|
||||
// Handles execution of prompt results.
|
||||
class PromptHandler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
PromptHandler() {}
|
||||
|
||||
// Called due to cefQuery execution.
|
||||
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) OVERRIDE {
|
||||
// Parse |request| which takes the form "Prompt.[type]:[value]".
|
||||
const std::string& request_str = request;
|
||||
if (request_str.find(kPrompt) != 0)
|
||||
return false;
|
||||
|
||||
std::string type = request_str.substr(sizeof(kPrompt) - 1);
|
||||
size_t delim = type.find(':');
|
||||
if (delim == std::string::npos)
|
||||
return false;
|
||||
|
||||
const std::string& value = type.substr(delim + 1);
|
||||
type = type.substr(0, delim);
|
||||
|
||||
// Canceling the prompt dialog returns a value of "null".
|
||||
if (value != "null") {
|
||||
if (type == kPromptFPS)
|
||||
SetFPS(browser, atoi(value.c_str()));
|
||||
else if (type == kPromptDSF)
|
||||
SetDSF(browser, static_cast<float>(atof(value.c_str())));
|
||||
}
|
||||
|
||||
// Nothing is done with the response.
|
||||
callback->Success(CefString());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetFPS(CefRefPtr<CefBrowser> browser, int fps) {
|
||||
if (fps <= 0) {
|
||||
// Reset to the default value.
|
||||
CefBrowserSettings settings;
|
||||
MainContext::Get()->PopulateBrowserSettings(&settings);
|
||||
fps = settings.windowless_frame_rate;
|
||||
}
|
||||
|
||||
browser->GetHost()->SetWindowlessFrameRate(fps);
|
||||
}
|
||||
|
||||
void SetDSF(CefRefPtr<CefBrowser> browser, float dsf) {
|
||||
MainMessageLoop::Get()->PostClosure(
|
||||
base::Bind(&PromptHandler::SetDSFOnMainThread, browser, dsf));
|
||||
}
|
||||
|
||||
static void SetDSFOnMainThread(CefRefPtr<CefBrowser> browser, float dsf) {
|
||||
RootWindow::GetForBrowser(browser->GetIdentifier())->
|
||||
SetDeviceScaleFactor(dsf);
|
||||
}
|
||||
};
|
||||
|
||||
void Prompt(CefRefPtr<CefBrowser> browser,
|
||||
const std::string& type,
|
||||
const std::string& label,
|
||||
const std::string& default_value) {
|
||||
// Prompt the user for a new value. Works as follows:
|
||||
// 1. Show a prompt() dialog via JavaScript.
|
||||
// 2. Pass the result to window.cefQuery().
|
||||
// 3. Handle the result in PromptHandler::OnQuery.
|
||||
const std::string& code =
|
||||
"window.cefQuery({'request': '" + std::string(kPrompt) + type +
|
||||
":' + prompt('" + label + "', '" + default_value + "')});";
|
||||
browser->GetMainFrame()->ExecuteJavaScript(
|
||||
code, browser->GetMainFrame()->GetURL(), 0);
|
||||
}
|
||||
|
||||
void PromptFPS(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&PromptFPS, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the default value string.
|
||||
std::stringstream ss;
|
||||
ss << browser->GetHost()->GetWindowlessFrameRate();
|
||||
|
||||
Prompt(browser, kPromptFPS, "Enter FPS", ss.str());
|
||||
}
|
||||
|
||||
void PromptDSF(CefRefPtr<CefBrowser> browser) {
|
||||
if (!MainMessageLoop::Get()->RunsTasksOnCurrentThread()) {
|
||||
// Execute on the main thread.
|
||||
MainMessageLoop::Get()->PostClosure(base::Bind(&PromptDSF, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the default value string.
|
||||
std::stringstream ss;
|
||||
ss << RootWindow::GetForBrowser(browser->GetIdentifier())->
|
||||
GetDeviceScaleFactor();
|
||||
|
||||
Prompt(browser, kPromptDSF, "Enter Device Scale Factor", ss.str());
|
||||
}
|
||||
|
||||
void BeginTracing() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&BeginTracing));
|
||||
return;
|
||||
}
|
||||
|
||||
CefBeginTracing(CefString(), NULL);
|
||||
}
|
||||
|
||||
void EndTracing(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&EndTracing, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
class Client : public CefEndTracingCallback,
|
||||
public CefRunFileDialogCallback {
|
||||
public:
|
||||
explicit Client(CefRefPtr<CefBrowser> browser)
|
||||
: browser_(browser) {
|
||||
RunDialog();
|
||||
}
|
||||
|
||||
void RunDialog() {
|
||||
static const char kDefaultFileName[] = "trace.txt";
|
||||
std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
|
||||
if (path.empty())
|
||||
path = kDefaultFileName;
|
||||
|
||||
// Results in a call to OnFileDialogDismissed.
|
||||
browser_->GetHost()->RunFileDialog(
|
||||
static_cast<cef_file_dialog_mode_t>(
|
||||
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG),
|
||||
CefString(), // title
|
||||
path,
|
||||
std::vector<CefString>(), // accept_filters
|
||||
0, // selected_accept_filter
|
||||
this);
|
||||
}
|
||||
|
||||
void OnFileDialogDismissed(
|
||||
int selected_accept_filter,
|
||||
const std::vector<CefString>& file_paths) OVERRIDE {
|
||||
if (!file_paths.empty()) {
|
||||
// File selected. Results in a call to OnEndTracingComplete.
|
||||
CefEndTracing(file_paths.front(), this);
|
||||
} else {
|
||||
// No file selected. Discard the trace data.
|
||||
CefEndTracing(CefString(), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void OnEndTracingComplete(
|
||||
const CefString& tracing_file) OVERRIDE {
|
||||
Alert(browser_,
|
||||
"File \"" + tracing_file.ToString() + "\" saved successfully.");
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(Client);
|
||||
};
|
||||
|
||||
new Client(browser);
|
||||
}
|
||||
|
||||
void PrintToPDF(CefRefPtr<CefBrowser> browser) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&PrintToPDF, browser));
|
||||
return;
|
||||
}
|
||||
|
||||
class Client : public CefPdfPrintCallback,
|
||||
public CefRunFileDialogCallback {
|
||||
public:
|
||||
explicit Client(CefRefPtr<CefBrowser> browser)
|
||||
: browser_(browser) {
|
||||
RunDialog();
|
||||
}
|
||||
|
||||
void RunDialog() {
|
||||
static const char kDefaultFileName[] = "output.pdf";
|
||||
std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
|
||||
if (path.empty())
|
||||
path = kDefaultFileName;
|
||||
|
||||
std::vector<CefString> accept_filters;
|
||||
accept_filters.push_back(".pdf");
|
||||
|
||||
// Results in a call to OnFileDialogDismissed.
|
||||
browser_->GetHost()->RunFileDialog(
|
||||
static_cast<cef_file_dialog_mode_t>(
|
||||
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG),
|
||||
CefString(), // title
|
||||
path,
|
||||
accept_filters,
|
||||
0, // selected_accept_filter
|
||||
this);
|
||||
}
|
||||
|
||||
void OnFileDialogDismissed(
|
||||
int selected_accept_filter,
|
||||
const std::vector<CefString>& file_paths) OVERRIDE {
|
||||
if (!file_paths.empty()) {
|
||||
CefPdfPrintSettings settings;
|
||||
|
||||
// Show the URL in the footer.
|
||||
settings.header_footer_enabled = true;
|
||||
CefString(&settings.header_footer_url) =
|
||||
browser_->GetMainFrame()->GetURL();
|
||||
|
||||
// Print to the selected PDF file.
|
||||
browser_->GetHost()->PrintToPDF(file_paths[0], settings, this);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPdfPrintFinished(const CefString& path, bool ok) OVERRIDE {
|
||||
Alert(browser_, "File \"" + path.ToString() +"\" " +
|
||||
(ok ? "saved successfully." : "failed to save."));
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(Client);
|
||||
};
|
||||
|
||||
new Client(browser);
|
||||
}
|
||||
|
||||
void RunOtherTests(CefRefPtr<CefBrowser> browser) {
|
||||
browser->GetMainFrame()->LoadURL("http://tests/other_tests");
|
||||
}
|
||||
|
||||
// Provider that dumps the request contents.
|
||||
class RequestDumpResourceProvider : public CefResourceManager::Provider {
|
||||
public:
|
||||
explicit RequestDumpResourceProvider(const std::string& url)
|
||||
: url_(url) {
|
||||
DCHECK(!url.empty());
|
||||
}
|
||||
|
||||
bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
const std::string& url = request->url();
|
||||
if (url != url_) {
|
||||
// Not handled by this provider.
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& dump = DumpRequestContents(request->request());
|
||||
std::string str = "<html><body bgcolor=\"white\"><pre>" + dump +
|
||||
"</pre></body></html>";
|
||||
CefRefPtr<CefStreamReader> stream =
|
||||
CefStreamReader::CreateForData(
|
||||
static_cast<void*>(const_cast<char*>(str.c_str())),
|
||||
str.size());
|
||||
DCHECK(stream.get());
|
||||
request->Continue(new CefStreamResourceHandler("text/html", stream));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string url_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
|
||||
};
|
||||
|
||||
// Add a file extension to |url| if none is currently specified.
|
||||
std::string RequestUrlFilter(const std::string& url) {
|
||||
if (url.find(kTestOrigin) != 0U) {
|
||||
// Don't filter anything outside of the test origin.
|
||||
return url;
|
||||
}
|
||||
|
||||
// Identify where the query or fragment component, if any, begins.
|
||||
size_t suffix_pos = url.find('?');
|
||||
if (suffix_pos == std::string::npos)
|
||||
suffix_pos = url.find('#');
|
||||
|
||||
std::string url_base, url_suffix;
|
||||
if (suffix_pos == std::string::npos) {
|
||||
url_base = url;
|
||||
} else {
|
||||
url_base = url.substr(0, suffix_pos);
|
||||
url_suffix = url.substr(suffix_pos);
|
||||
}
|
||||
|
||||
// Identify the last path component.
|
||||
size_t path_pos = url_base.rfind('/');
|
||||
if (path_pos == std::string::npos)
|
||||
return url;
|
||||
|
||||
const std::string& path_component = url_base.substr(path_pos);
|
||||
|
||||
// Identify if a file extension is currently specified.
|
||||
size_t ext_pos = path_component.rfind(".");
|
||||
if (ext_pos != std::string::npos)
|
||||
return url;
|
||||
|
||||
// Rebuild the URL with a file extension.
|
||||
return url_base + ".html" + url_suffix;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void RunTest(CefRefPtr<CefBrowser> browser, int id) {
|
||||
if (!browser)
|
||||
return;
|
||||
|
||||
switch (id) {
|
||||
case ID_TESTS_GETSOURCE:
|
||||
RunGetSourceTest(browser);
|
||||
break;
|
||||
case ID_TESTS_GETTEXT:
|
||||
RunGetTextTest(browser);
|
||||
break;
|
||||
case ID_TESTS_WINDOW_NEW:
|
||||
RunNewWindowTest(browser);
|
||||
break;
|
||||
case ID_TESTS_WINDOW_POPUP:
|
||||
RunPopupWindowTest(browser);
|
||||
break;
|
||||
case ID_TESTS_REQUEST:
|
||||
RunRequestTest(browser);
|
||||
break;
|
||||
case ID_TESTS_PLUGIN_INFO:
|
||||
RunPluginInfoTest(browser);
|
||||
break;
|
||||
case ID_TESTS_ZOOM_IN:
|
||||
ModifyZoom(browser, 0.5);
|
||||
break;
|
||||
case ID_TESTS_ZOOM_OUT:
|
||||
ModifyZoom(browser, -0.5);
|
||||
break;
|
||||
case ID_TESTS_ZOOM_RESET:
|
||||
browser->GetHost()->SetZoomLevel(0.0);
|
||||
break;
|
||||
case ID_TESTS_OSR_FPS:
|
||||
PromptFPS(browser);
|
||||
break;
|
||||
case ID_TESTS_OSR_DSF:
|
||||
PromptDSF(browser);
|
||||
break;
|
||||
case ID_TESTS_TRACING_BEGIN:
|
||||
BeginTracing();
|
||||
break;
|
||||
case ID_TESTS_TRACING_END:
|
||||
EndTracing(browser);
|
||||
break;
|
||||
case ID_TESTS_PRINT:
|
||||
browser->GetHost()->Print();
|
||||
break;
|
||||
case ID_TESTS_PRINT_TO_PDF:
|
||||
PrintToPDF(browser);
|
||||
break;
|
||||
case ID_TESTS_OTHER_TESTS:
|
||||
RunOtherTests(browser);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DumpRequestContents(CefRefPtr<CefRequest> request) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "URL: " << std::string(request->GetURL());
|
||||
ss << "\nMethod: " << std::string(request->GetMethod());
|
||||
|
||||
CefRequest::HeaderMap headerMap;
|
||||
request->GetHeaderMap(headerMap);
|
||||
if (headerMap.size() > 0) {
|
||||
ss << "\nHeaders:";
|
||||
CefRequest::HeaderMap::const_iterator it = headerMap.begin();
|
||||
for (; it != headerMap.end(); ++it) {
|
||||
ss << "\n\t" << std::string((*it).first) << ": " <<
|
||||
std::string((*it).second);
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefPostData> postData = request->GetPostData();
|
||||
if (postData.get()) {
|
||||
CefPostData::ElementVector elements;
|
||||
postData->GetElements(elements);
|
||||
if (elements.size() > 0) {
|
||||
ss << "\nPost Data:";
|
||||
CefRefPtr<CefPostDataElement> element;
|
||||
CefPostData::ElementVector::const_iterator it = elements.begin();
|
||||
for (; it != elements.end(); ++it) {
|
||||
element = (*it);
|
||||
if (element->GetType() == PDE_TYPE_BYTES) {
|
||||
// the element is composed of bytes
|
||||
ss << "\n\tBytes: ";
|
||||
if (element->GetBytesCount() == 0) {
|
||||
ss << "(empty)";
|
||||
} else {
|
||||
// retrieve the data.
|
||||
size_t size = element->GetBytesCount();
|
||||
char* bytes = new char[size];
|
||||
element->GetBytes(size, bytes);
|
||||
ss << std::string(bytes, size);
|
||||
delete [] bytes;
|
||||
}
|
||||
} else if (element->GetType() == PDE_TYPE_FILE) {
|
||||
ss << "\n\tFile: " << std::string(element->GetFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GetDataURI(const std::string& data,
|
||||
const std::string& mime_type) {
|
||||
return "data:" + mime_type + ";base64," +
|
||||
CefURIEncode(CefBase64Encode(data.data(), data.size()), false).ToString();
|
||||
}
|
||||
|
||||
std::string GetErrorString(cef_errorcode_t code) {
|
||||
// Case condition that returns |code| as a string.
|
||||
#define CASE(code) case code: return #code
|
||||
|
||||
switch (code) {
|
||||
CASE(ERR_NONE);
|
||||
CASE(ERR_FAILED);
|
||||
CASE(ERR_ABORTED);
|
||||
CASE(ERR_INVALID_ARGUMENT);
|
||||
CASE(ERR_INVALID_HANDLE);
|
||||
CASE(ERR_FILE_NOT_FOUND);
|
||||
CASE(ERR_TIMED_OUT);
|
||||
CASE(ERR_FILE_TOO_BIG);
|
||||
CASE(ERR_UNEXPECTED);
|
||||
CASE(ERR_ACCESS_DENIED);
|
||||
CASE(ERR_NOT_IMPLEMENTED);
|
||||
CASE(ERR_CONNECTION_CLOSED);
|
||||
CASE(ERR_CONNECTION_RESET);
|
||||
CASE(ERR_CONNECTION_REFUSED);
|
||||
CASE(ERR_CONNECTION_ABORTED);
|
||||
CASE(ERR_CONNECTION_FAILED);
|
||||
CASE(ERR_NAME_NOT_RESOLVED);
|
||||
CASE(ERR_INTERNET_DISCONNECTED);
|
||||
CASE(ERR_SSL_PROTOCOL_ERROR);
|
||||
CASE(ERR_ADDRESS_INVALID);
|
||||
CASE(ERR_ADDRESS_UNREACHABLE);
|
||||
CASE(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
|
||||
CASE(ERR_TUNNEL_CONNECTION_FAILED);
|
||||
CASE(ERR_NO_SSL_VERSIONS_ENABLED);
|
||||
CASE(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
|
||||
CASE(ERR_SSL_RENEGOTIATION_REQUESTED);
|
||||
CASE(ERR_CERT_COMMON_NAME_INVALID);
|
||||
CASE(ERR_CERT_DATE_INVALID);
|
||||
CASE(ERR_CERT_AUTHORITY_INVALID);
|
||||
CASE(ERR_CERT_CONTAINS_ERRORS);
|
||||
CASE(ERR_CERT_NO_REVOCATION_MECHANISM);
|
||||
CASE(ERR_CERT_UNABLE_TO_CHECK_REVOCATION);
|
||||
CASE(ERR_CERT_REVOKED);
|
||||
CASE(ERR_CERT_INVALID);
|
||||
CASE(ERR_CERT_END);
|
||||
CASE(ERR_INVALID_URL);
|
||||
CASE(ERR_DISALLOWED_URL_SCHEME);
|
||||
CASE(ERR_UNKNOWN_URL_SCHEME);
|
||||
CASE(ERR_TOO_MANY_REDIRECTS);
|
||||
CASE(ERR_UNSAFE_REDIRECT);
|
||||
CASE(ERR_UNSAFE_PORT);
|
||||
CASE(ERR_INVALID_RESPONSE);
|
||||
CASE(ERR_INVALID_CHUNKED_ENCODING);
|
||||
CASE(ERR_METHOD_NOT_SUPPORTED);
|
||||
CASE(ERR_UNEXPECTED_PROXY_AUTH);
|
||||
CASE(ERR_EMPTY_RESPONSE);
|
||||
CASE(ERR_RESPONSE_HEADERS_TOO_BIG);
|
||||
CASE(ERR_CACHE_MISS);
|
||||
CASE(ERR_INSECURE_RESPONSE);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager) {
|
||||
const std::string& test_origin = kTestOrigin;
|
||||
|
||||
// Add the URL filter.
|
||||
resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));
|
||||
|
||||
// Add provider for resource dumps.
|
||||
resource_manager->AddProvider(
|
||||
new RequestDumpResourceProvider(test_origin + "request.html"),
|
||||
0, std::string());
|
||||
|
||||
// Add provider for bundled resource files.
|
||||
#if defined(OS_WIN)
|
||||
// Read resources from the binary.
|
||||
resource_manager->AddProvider(CreateBinaryResourceProvider(test_origin),
|
||||
100, std::string());
|
||||
#elif defined(OS_POSIX)
|
||||
// Read resources from a directory on disk.
|
||||
std::string resource_dir;
|
||||
if (GetResourceDir(resource_dir)) {
|
||||
resource_manager->AddDirectoryProvider(test_origin, resource_dir,
|
||||
100, std::string());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message) {
|
||||
// Escape special characters in the message.
|
||||
std::string msg = StringReplace(message, "\\", "\\\\");
|
||||
msg = StringReplace(msg, "'", "\\'");
|
||||
|
||||
// Execute a JavaScript alert().
|
||||
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
|
||||
frame->ExecuteJavaScript("alert('" + msg + "');", frame->GetURL(), 0);
|
||||
}
|
||||
|
||||
void CreateMessageHandlers(MessageHandlerSet& handlers) {
|
||||
handlers.insert(new PromptHandler);
|
||||
|
||||
// Create the dialog test handlers.
|
||||
dialog_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the binding test handlers.
|
||||
binding_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the urlrequest test handlers.
|
||||
urlrequest_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the window test handlers.
|
||||
window_test::CreateMessageHandlers(handlers);
|
||||
}
|
||||
|
||||
void RegisterSchemeHandlers() {
|
||||
// Register the scheme handler.
|
||||
scheme_test::RegisterSchemeHandlers();
|
||||
}
|
||||
|
||||
} // namespace test_runner
|
||||
} // namespace client
|
||||
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_TEST_RUNNER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_TEST_RUNNER_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "include/cef_browser.h"
|
||||
#include "include/cef_request.h"
|
||||
#include "include/wrapper/cef_message_router.h"
|
||||
#include "include/wrapper/cef_resource_manager.h"
|
||||
|
||||
namespace client {
|
||||
namespace test_runner {
|
||||
|
||||
// Run a test.
|
||||
void RunTest(CefRefPtr<CefBrowser> browser, int id);
|
||||
|
||||
// Returns the contents of the CefRequest as a string.
|
||||
std::string DumpRequestContents(CefRefPtr<CefRequest> request);
|
||||
|
||||
// Returns a data: URI with the specified contents.
|
||||
std::string GetDataURI(const std::string& data,
|
||||
const std::string& mime_type);
|
||||
|
||||
// Returns the string representation of the specified error code.
|
||||
std::string GetErrorString(cef_errorcode_t code);
|
||||
|
||||
// Set up the resource manager for tests.
|
||||
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager);
|
||||
|
||||
// Show a JS alert message.
|
||||
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message);
|
||||
|
||||
// Create all CefMessageRouterBrowserSide::Handler objects. They will be
|
||||
// deleted when the ClientHandler is destroyed.
|
||||
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
|
||||
void CreateMessageHandlers(MessageHandlerSet& handlers);
|
||||
|
||||
// Register scheme handlers for tests.
|
||||
void RegisterSchemeHandlers();
|
||||
|
||||
} // namespace test_runner
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEST_RUNNER_H_
|
||||
@ -0,0 +1,190 @@
|
||||
// Copyright (c) 2015 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 "cefclient/browser/urlrequest_test.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
namespace client {
|
||||
namespace urlrequest_test {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestUrl[] = "http://tests/urlrequest";
|
||||
const char kTestMessageName[] = "URLRequestTest";
|
||||
|
||||
// Implementation of CefURLRequestClient that stores response information. Only
|
||||
// accessed on the UI thread.
|
||||
class RequestClient : public CefURLRequestClient {
|
||||
public:
|
||||
// Callback to be executed on request completion.
|
||||
typedef base::Callback<void(CefURLRequest::ErrorCode /*error_code*/,
|
||||
const std::string& /*download_data*/)> Callback;
|
||||
|
||||
explicit RequestClient(const Callback& callback)
|
||||
: callback_(callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(!callback_.is_null());
|
||||
}
|
||||
|
||||
void Detach() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!callback_.is_null())
|
||||
callback_.Reset();
|
||||
}
|
||||
|
||||
void OnRequestComplete(CefRefPtr<CefURLRequest> request) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!callback_.is_null()) {
|
||||
callback_.Run(request->GetRequestError(), download_data_);
|
||||
callback_.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void OnUploadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) OVERRIDE {
|
||||
}
|
||||
|
||||
void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
|
||||
int64 current,
|
||||
int64 total) OVERRIDE {
|
||||
}
|
||||
|
||||
void OnDownloadData(CefRefPtr<CefURLRequest> request,
|
||||
const void* data,
|
||||
size_t data_length) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
download_data_ += std::string(static_cast<const char*>(data), data_length);
|
||||
}
|
||||
|
||||
bool GetAuthCredentials(bool isProxy,
|
||||
const CefString& host,
|
||||
int port,
|
||||
const CefString& realm,
|
||||
const CefString& scheme,
|
||||
CefRefPtr<CefAuthCallback> callback) OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Callback callback_;
|
||||
std::string download_data_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(RequestClient);
|
||||
DISALLOW_COPY_AND_ASSIGN(RequestClient);
|
||||
};
|
||||
|
||||
// Handle messages in the browser process. Only accessed on the UI thread.
|
||||
class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
Handler() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
}
|
||||
|
||||
~Handler() {
|
||||
CancelPendingRequest();
|
||||
}
|
||||
|
||||
// Called due to cefQuery execution in urlrequest.html.
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) OVERRIDE {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Only handle messages from the test URL.
|
||||
std::string url = frame->GetURL();
|
||||
if (url.find(kTestUrl) != 0)
|
||||
return false;
|
||||
|
||||
const std::string& message_name = request;
|
||||
if (message_name.find(kTestMessageName) == 0) {
|
||||
url = message_name.substr(sizeof(kTestMessageName));
|
||||
|
||||
CancelPendingRequest();
|
||||
|
||||
DCHECK(!callback_.get());
|
||||
DCHECK(!urlrequest_.get());
|
||||
|
||||
callback_ = callback;
|
||||
|
||||
// Create a CefRequest for the specified URL.
|
||||
CefRefPtr<CefRequest> cef_request = CefRequest::Create();
|
||||
cef_request->SetURL(url);
|
||||
cef_request->SetMethod("GET");
|
||||
|
||||
// Callback to be executed on request completion.
|
||||
// It's safe to use base::Unretained() here because there is only one
|
||||
// RequestClient pending at any given time and we explicitly detach the
|
||||
// callback in the Handler destructor.
|
||||
const RequestClient::Callback& request_callback =
|
||||
base::Bind(&Handler::OnRequestComplete, base::Unretained(this));
|
||||
|
||||
// Create and start the new CefURLRequest.
|
||||
urlrequest_ = CefURLRequest::Create(cef_request,
|
||||
new RequestClient(request_callback),
|
||||
NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Cancel the currently pending URL request, if any.
|
||||
void CancelPendingRequest() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (urlrequest_.get()) {
|
||||
// Don't execute the callback when we explicitly cancel the request.
|
||||
static_cast<RequestClient*>(urlrequest_->GetClient().get())->Detach();
|
||||
|
||||
urlrequest_->Cancel();
|
||||
urlrequest_ = NULL;
|
||||
}
|
||||
|
||||
if (callback_.get()) {
|
||||
// Must always execute |callback_| before deleting it.
|
||||
callback_->Failure(ERR_ABORTED, test_runner::GetErrorString(ERR_ABORTED));
|
||||
callback_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void OnRequestComplete(CefURLRequest::ErrorCode error_code,
|
||||
const std::string& download_data) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (error_code == ERR_NONE)
|
||||
callback_->Success(download_data);
|
||||
else
|
||||
callback_->Failure(error_code, test_runner::GetErrorString(error_code));
|
||||
|
||||
callback_ = NULL;
|
||||
urlrequest_ = NULL;
|
||||
}
|
||||
|
||||
CefRefPtr<Callback> callback_;
|
||||
CefRefPtr<CefURLRequest> urlrequest_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Handler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
|
||||
handlers.insert(new Handler());
|
||||
}
|
||||
|
||||
} // namespace urlrequest_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_BROWSER_URLREQUEST_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_URLREQUEST_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client {
|
||||
namespace urlrequest_test {
|
||||
|
||||
// Create message handlers. Called from test_runner.cc.
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
|
||||
|
||||
} // namespace urlrequest_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_URLREQUEST_TEST_H_
|
||||
@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2013 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 "cefclient/browser/window_test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "cefclient/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
namespace window_test {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestUrl[] = "http://tests/window";
|
||||
const char kMessagePositionName[] = "WindowTest.Position";
|
||||
const char kMessageMinimizeName[] = "WindowTest.Minimize";
|
||||
const char kMessageMaximizeName[] = "WindowTest.Maximize";
|
||||
const char kMessageRestoreName[] = "WindowTest.Restore";
|
||||
|
||||
// Handle messages in the browser process.
|
||||
class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
|
||||
// Called due to cefBroadcast execution in window.html.
|
||||
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) OVERRIDE {
|
||||
// Only handle messages from the test URL.
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestUrl) != 0)
|
||||
return false;
|
||||
|
||||
const std::string& message_name = request;
|
||||
if (message_name.find(kMessagePositionName) == 0) {
|
||||
// Parse the comma-delimited list of integer values.
|
||||
std::vector<int> vec;
|
||||
const std::string& vals =
|
||||
message_name.substr(sizeof(kMessagePositionName));
|
||||
std::stringstream ss(vals);
|
||||
int i;
|
||||
while (ss >> i) {
|
||||
vec.push_back(i);
|
||||
if (ss.peek() == ',')
|
||||
ss.ignore();
|
||||
}
|
||||
|
||||
if (vec.size() == 4) {
|
||||
// Execute SetPos() on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&SetPos, browser,
|
||||
vec[0], vec[1], vec[2], vec[3]));
|
||||
}
|
||||
} else if (message_name == kMessageMinimizeName) {
|
||||
// Execute Minimize() on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&Minimize, browser));
|
||||
} else if (message_name == kMessageMaximizeName) {
|
||||
// Execute Maximize() on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&Maximize, browser));
|
||||
} else if (message_name == kMessageRestoreName) {
|
||||
// Execute Restore() on the main thread.
|
||||
MAIN_POST_CLOSURE(base::Bind(&Restore, browser));
|
||||
} else {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
callback->Success("");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void ModifyBounds(const CefRect& display, CefRect& window) {
|
||||
window.x += display.x;
|
||||
window.y += display.y;
|
||||
|
||||
if (window.x < display.x)
|
||||
window.x = display.x;
|
||||
if (window.y < display.y)
|
||||
window.y = display.y;
|
||||
if (window.width < 100)
|
||||
window.width = 100;
|
||||
else if (window.width >= display.width)
|
||||
window.width = display.width;
|
||||
if (window.height < 100)
|
||||
window.height = 100;
|
||||
else if (window.height >= display.height)
|
||||
window.height = display.height;
|
||||
if (window.x + window.width >= display.x + display.width)
|
||||
window.x = display.x + display.width - window.width;
|
||||
if (window.y + window.height >= display.y + display.height)
|
||||
window.y = display.y + display.height - window.height;
|
||||
}
|
||||
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
|
||||
handlers.insert(new Handler());
|
||||
}
|
||||
|
||||
} // namespace window_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2013 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 CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client {
|
||||
namespace window_test {
|
||||
|
||||
// Create message handlers. Called from test_runner.cc.
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
|
||||
|
||||
// Fit |window| inside |display|. Coordinates are relative to the upper-left
|
||||
// corner of the display.
|
||||
void ModifyBounds(const CefRect& display, CefRect& window);
|
||||
|
||||
// Platform implementations.
|
||||
void SetPos(CefRefPtr<CefBrowser> browser,
|
||||
int x, int y, int width, int height);
|
||||
void Minimize(CefRefPtr<CefBrowser> browser);
|
||||
void Maximize(CefRefPtr<CefBrowser> browser);
|
||||
void Restore(CefRefPtr<CefBrowser> browser);
|
||||
|
||||
} // namespace window_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_TEST_H_
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2013 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 "cefclient/browser/window_test.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "cefclient/browser/root_window.h"
|
||||
|
||||
namespace client {
|
||||
namespace window_test {
|
||||
|
||||
namespace {
|
||||
|
||||
GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||
if (root_window.get())
|
||||
return GTK_WINDOW(root_window->GetWindowHandle());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool IsMaximized(GtkWindow* window) {
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||
gint state = gdk_window_get_state(gdk_window);
|
||||
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetPos(CefRefPtr<CefBrowser> browser, int x, int y, int width,
|
||||
int height) {
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||
|
||||
// Make sure the window isn't minimized or maximized.
|
||||
if (IsMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
else
|
||||
gtk_window_present(window);
|
||||
|
||||
// Retrieve information about the display that contains the window.
|
||||
GdkScreen* screen = gdk_screen_get_default();
|
||||
gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
|
||||
GdkRectangle rect;
|
||||
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
||||
|
||||
// Make sure the window is inside the display.
|
||||
CefRect display_rect(rect.x, rect.y, rect.width, rect.height);
|
||||
CefRect window_rect(x, y, width, height);
|
||||
ModifyBounds(display_rect, window_rect);
|
||||
|
||||
gdk_window_move_resize(gdk_window, window_rect.x, window_rect.y,
|
||||
window_rect.width, window_rect.height);
|
||||
}
|
||||
|
||||
void Minimize(CefRefPtr<CefBrowser> browser) {
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
|
||||
// Unmaximize the window before minimizing so restore behaves correctly.
|
||||
if (IsMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
|
||||
gtk_window_iconify(window);
|
||||
}
|
||||
|
||||
void Maximize(CefRefPtr<CefBrowser> browser) {
|
||||
gtk_window_maximize(GetWindow(browser));
|
||||
}
|
||||
|
||||
void Restore(CefRefPtr<CefBrowser> browser) {
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (IsMaximized(window))
|
||||
gtk_window_unmaximize(window);
|
||||
else
|
||||
gtk_window_present(window);
|
||||
}
|
||||
|
||||
} // namespace window_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2013 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 <gtk/gtk.h>
|
||||
#include <gtk/gtkgl.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#undef Success // Definition conflicts with cef_message_router.h
|
||||
#undef RootWindow // Definition conflicts with root_window.h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_app.h"
|
||||
#include "include/cef_command_line.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "cefclient/browser/client_app_browser.h"
|
||||
#include "cefclient/browser/main_context_impl.h"
|
||||
#include "cefclient/browser/main_message_loop_std.h"
|
||||
#include "cefclient/browser/test_runner.h"
|
||||
#include "cefclient/common/client_app_other.h"
|
||||
#include "cefclient/renderer/client_app_renderer.h"
|
||||
|
||||
namespace client {
|
||||
namespace {
|
||||
|
||||
int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
|
||||
LOG(WARNING)
|
||||
<< "X error received: "
|
||||
<< "type " << event->type << ", "
|
||||
<< "serial " << event->serial << ", "
|
||||
<< "error_code " << static_cast<int>(event->error_code) << ", "
|
||||
<< "request_code " << static_cast<int>(event->request_code) << ", "
|
||||
<< "minor_code " << static_cast<int>(event->minor_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XIOErrorHandlerImpl(Display *display) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TerminationSignalHandler(int signatl) {
|
||||
LOG(ERROR) << "Received termination signal: " << signatl;
|
||||
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
|
||||
}
|
||||
|
||||
int RunMain(int argc, char* argv[]) {
|
||||
// Create a copy of |argv| on Linux because Chromium mangles the value
|
||||
// internally (see issue #620).
|
||||
CefScopedArgArray scoped_arg_array(argc, argv);
|
||||
char** argv_copy = scoped_arg_array.array();
|
||||
|
||||
CefMainArgs main_args(argc, argv);
|
||||
|
||||
// Parse command-line arguments.
|
||||
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
|
||||
command_line->InitFromArgv(argc, argv);
|
||||
|
||||
// Create a ClientApp of the correct type.
|
||||
CefRefPtr<CefApp> app;
|
||||
ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line);
|
||||
if (process_type == ClientApp::BrowserProcess) {
|
||||
app = new ClientAppBrowser();
|
||||
} else if (process_type == ClientApp::RendererProcess ||
|
||||
process_type == ClientApp::ZygoteProcess) {
|
||||
// On Linux the zygote process is used to spawn other process types. Since
|
||||
// we don't know what type of process it will be give it the renderer
|
||||
// client.
|
||||
app = new ClientAppRenderer();
|
||||
} else if (process_type == ClientApp::OtherProcess) {
|
||||
app = new ClientAppOther();
|
||||
}
|
||||
|
||||
// Execute the secondary process, if any.
|
||||
int exit_code = CefExecuteProcess(main_args, app, NULL);
|
||||
if (exit_code >= 0)
|
||||
return exit_code;
|
||||
|
||||
// Create the main context object.
|
||||
scoped_ptr<MainContextImpl> context(new MainContextImpl(command_line, true));
|
||||
|
||||
CefSettings settings;
|
||||
|
||||
// Populate the settings based on command line arguments.
|
||||
context->PopulateSettings(&settings);
|
||||
|
||||
// Install xlib error handlers so that the application won't be terminated
|
||||
// on non-fatal errors.
|
||||
XSetErrorHandler(XErrorHandlerImpl);
|
||||
XSetIOErrorHandler(XIOErrorHandlerImpl);
|
||||
|
||||
// Create the main message loop object.
|
||||
scoped_ptr<MainMessageLoop> message_loop(new MainMessageLoopStd);
|
||||
|
||||
// Initialize CEF.
|
||||
context->Initialize(main_args, settings, app, NULL);
|
||||
|
||||
// The Chromium sandbox requires that there only be a single thread during
|
||||
// initialization. Therefore initialize GTK after CEF.
|
||||
gtk_init(&argc, &argv_copy);
|
||||
|
||||
// Perform gtkglext initialization required by the OSR example.
|
||||
gtk_gl_init(&argc, &argv_copy);
|
||||
|
||||
// Install a signal handler so we clean up after ourselves.
|
||||
signal(SIGINT, TerminationSignalHandler);
|
||||
signal(SIGTERM, TerminationSignalHandler);
|
||||
|
||||
// Register scheme handlers.
|
||||
test_runner::RegisterSchemeHandlers();
|
||||
|
||||
// Create the first window.
|
||||
context->GetRootWindowManager()->CreateRootWindow(
|
||||
true, // Show controls.
|
||||
settings.windowless_rendering_enabled ? true : false,
|
||||
CefRect(), // Use default system size.
|
||||
std::string()); // Use default URL.
|
||||
|
||||
// Run the message loop. This will block until Quit() is called.
|
||||
int result = message_loop->Run();
|
||||
|
||||
// Shut down CEF.
|
||||
context->Shutdown();
|
||||
|
||||
// Release objects in reverse order of creation.
|
||||
message_loop.reset();
|
||||
context.reset();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace client
|
||||
|
||||
|
||||
// Program entry point function.
|
||||
int main(int argc, char* argv[]) {
|
||||
return client::RunMain(argc, argv);
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2013 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 "cefclient/common/client_app.h"
|
||||
|
||||
#include "include/cef_command_line.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
// These flags must match the Chromium values.
|
||||
const char kProcessType[] = "type";
|
||||
const char kRendererProcess[] = "renderer";
|
||||
#if defined(OS_LINUX)
|
||||
const char kZygoteProcess[] = "zygote";
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
ClientApp::ClientApp() {
|
||||
}
|
||||
|
||||
// static
|
||||
ClientApp::ProcessType ClientApp::GetProcessType(
|
||||
CefRefPtr<CefCommandLine> command_line) {
|
||||
// The command-line flag won't be specified for the browser process.
|
||||
if (!command_line->HasSwitch(kProcessType))
|
||||
return BrowserProcess;
|
||||
|
||||
const std::string& process_type = command_line->GetSwitchValue(kProcessType);
|
||||
if (process_type == kRendererProcess)
|
||||
return RendererProcess;
|
||||
#if defined(OS_LINUX)
|
||||
else if (process_type == kZygoteProcess)
|
||||
return ZygoteProcess;
|
||||
#endif
|
||||
|
||||
return OtherProcess;
|
||||
}
|
||||
|
||||
void ClientApp::OnRegisterCustomSchemes(
|
||||
CefRefPtr<CefSchemeRegistrar> registrar) {
|
||||
RegisterCustomSchemes(registrar, cookieable_schemes_);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2013 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 CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_
|
||||
#define CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "include/cef_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Base class for customizing process-type-based behavior.
|
||||
class ClientApp : public CefApp {
|
||||
public:
|
||||
ClientApp();
|
||||
|
||||
enum ProcessType {
|
||||
BrowserProcess,
|
||||
RendererProcess,
|
||||
ZygoteProcess,
|
||||
OtherProcess,
|
||||
};
|
||||
|
||||
// Determine the process type based on command-line arguments.
|
||||
static ProcessType GetProcessType(CefRefPtr<CefCommandLine> command_line);
|
||||
|
||||
protected:
|
||||
// Schemes that will be registered with the global cookie manager.
|
||||
std::vector<CefString> cookieable_schemes_;
|
||||
|
||||
private:
|
||||
// Registers custom schemes. Implemented by cefclient in
|
||||
// client_app_delegates_common.cc
|
||||
static void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
|
||||
std::vector<CefString>& cookiable_schemes);
|
||||
|
||||
// CefApp methods.
|
||||
void OnRegisterCustomSchemes(
|
||||
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientApp);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_
|
||||
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2012 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 "cefclient/common/client_app.h"
|
||||
#include "cefclient/common/scheme_test_common.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// static
|
||||
void ClientApp::RegisterCustomSchemes(
|
||||
CefRefPtr<CefSchemeRegistrar> registrar,
|
||||
std::vector<CefString>& cookiable_schemes) {
|
||||
scheme_test::RegisterCustomSchemes(registrar, cookiable_schemes);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2015 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 "cefclient/common/client_app_other.h"
|
||||
|
||||
#include "include/cef_command_line.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ClientAppOther::ClientAppOther() {
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2015 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 CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_OTHER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_OTHER_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/common/client_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client app implementation for other process types.
|
||||
class ClientAppOther : public ClientApp {
|
||||
public:
|
||||
ClientAppOther();
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(ClientAppOther);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientAppOther);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_OTHER_H_
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2013 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 "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
namespace switches {
|
||||
|
||||
// CEF and Chromium support a wide range of command-line switches. This file
|
||||
// only contains command-line switches specific to the cefclient application.
|
||||
// View CEF/Chromium documentation or search for *_switches.cc files in the
|
||||
// Chromium source code to identify other existing command-line switches.
|
||||
// Below is a partial listing of relevant *_switches.cc files:
|
||||
// base/base_switches.cc
|
||||
// cef/libcef/common/cef_switches.cc
|
||||
// chrome/common/chrome_switches.cc (not all apply)
|
||||
// content/public/common/content_switches.cc
|
||||
|
||||
const char kMultiThreadedMessageLoop[] = "multi-threaded-message-loop";
|
||||
const char kCachePath[] = "cache-path";
|
||||
const char kUrl[] = "url";
|
||||
const char kOffScreenRenderingEnabled[] = "off-screen-rendering-enabled";
|
||||
const char kOffScreenFrameRate[] = "off-screen-frame-rate";
|
||||
const char kTransparentPaintingEnabled[] = "transparent-painting-enabled";
|
||||
const char kShowUpdateRect[] = "show-update-rect";
|
||||
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
|
||||
const char kRequestContextPerBrowser[] = "request-context-per-browser";
|
||||
const char kBackgroundColor[] = "background-color";
|
||||
const char kEnableGPU[] = "enable-gpu";
|
||||
|
||||
} // namespace switches
|
||||
} // namespace client
|
||||
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2013 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.
|
||||
|
||||
// Defines all of the command line switches used by cefclient.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_
|
||||
#define CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_
|
||||
#pragma once
|
||||
|
||||
namespace client {
|
||||
namespace switches {
|
||||
|
||||
extern const char kMultiThreadedMessageLoop[];
|
||||
extern const char kCachePath[];
|
||||
extern const char kUrl[];
|
||||
extern const char kOffScreenRenderingEnabled[];
|
||||
extern const char kOffScreenFrameRate[];
|
||||
extern const char kTransparentPaintingEnabled[];
|
||||
extern const char kShowUpdateRect[];
|
||||
extern const char kMouseCursorChangeDisabled[];
|
||||
extern const char kRequestContextPerBrowser[];
|
||||
extern const char kBackgroundColor[];
|
||||
extern const char kEnableGPU[];
|
||||
|
||||
} // namespace switches
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_
|
||||
@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2012 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 "cefclient/common/scheme_test_common.h"
|
||||
|
||||
#include "include/cef_scheme.h"
|
||||
|
||||
namespace client {
|
||||
namespace scheme_test {
|
||||
|
||||
void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
|
||||
std::vector<CefString>& cookiable_schemes) {
|
||||
registrar->AddCustomScheme("client", true, false, false);
|
||||
}
|
||||
|
||||
} // namespace scheme_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_COMMON_SCHEME_TEST_COMMON_H_
|
||||
#define CEF_TESTS_CEFCLIENT_COMMON_SCHEME_TEST_COMMON_H_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "include/cef_scheme.h"
|
||||
|
||||
namespace client {
|
||||
namespace scheme_test {
|
||||
|
||||
// Register the custom scheme name/type. This must be done in all processes.
|
||||
// See browser/scheme_test.h for creation/registration of the custom scheme
|
||||
// handler which only occurs in the browser process. Called from
|
||||
// client_app_delegates_common.cc.
|
||||
void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
|
||||
std::vector<CefString>& cookiable_schemes);
|
||||
|
||||
} // namespace scheme_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_COMMON_SCHEME_TEST_COMMON_H_
|
||||
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2012 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 "cefclient/renderer/client_app_renderer.h"
|
||||
#include "cefclient/renderer/client_renderer.h"
|
||||
#include "cefclient/renderer/performance_test.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// static
|
||||
void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) {
|
||||
renderer::CreateDelegates(delegates);
|
||||
performance_test::CreateDelegates(delegates);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,120 @@
|
||||
// Copyright (c) 2013 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 "cefclient/renderer/client_app_renderer.h"
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
ClientAppRenderer::ClientAppRenderer() {
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnRenderThreadCreated(
|
||||
CefRefPtr<CefListValue> extra_info) {
|
||||
CreateDelegates(delegates_);
|
||||
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnRenderThreadCreated(this, extra_info);
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnWebKitInitialized() {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnWebKitInitialized(this);
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnBrowserDestroyed(this, browser);
|
||||
}
|
||||
|
||||
CefRefPtr<CefLoadHandler> ClientAppRenderer::GetLoadHandler() {
|
||||
CefRefPtr<CefLoadHandler> load_handler;
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end() && !load_handler.get(); ++it)
|
||||
load_handler = (*it)->GetLoadHandler(this);
|
||||
|
||||
return load_handler;
|
||||
}
|
||||
|
||||
bool ClientAppRenderer::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
NavigationType navigation_type,
|
||||
bool is_redirect) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it) {
|
||||
if ((*it)->OnBeforeNavigation(this, browser, frame, request,
|
||||
navigation_type, is_redirect)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnContextCreated(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnContextCreated(this, browser, frame, context);
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnContextReleased(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnContextReleased(this, browser, frame, context);
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnUncaughtException(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it) {
|
||||
(*it)->OnUncaughtException(this, browser, frame, context, exception,
|
||||
stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAppRenderer::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) {
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end(); ++it)
|
||||
(*it)->OnFocusedNodeChanged(this, browser, frame, node);
|
||||
}
|
||||
|
||||
bool ClientAppRenderer::OnProcessMessageReceived(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
DCHECK_EQ(source_process, PID_BROWSER);
|
||||
|
||||
bool handled = false;
|
||||
|
||||
DelegateSet::iterator it = delegates_.begin();
|
||||
for (; it != delegates_.end() && !handled; ++it) {
|
||||
handled = (*it)->OnProcessMessageReceived(this, browser, source_process,
|
||||
message);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2013 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 CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "cefclient/common/client_app.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Client app implementation for the renderer process.
|
||||
class ClientAppRenderer : public ClientApp,
|
||||
public CefRenderProcessHandler {
|
||||
public:
|
||||
// Interface for renderer delegates. All Delegates must be returned via
|
||||
// CreateDelegates. Do not perform work in the Delegate
|
||||
// constructor. See CefRenderProcessHandler for documentation.
|
||||
class Delegate : public virtual CefBase {
|
||||
public:
|
||||
virtual void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefListValue> extra_info) {}
|
||||
|
||||
virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {}
|
||||
|
||||
virtual void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser) {}
|
||||
|
||||
virtual void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser) {}
|
||||
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler(
|
||||
CefRefPtr<ClientAppRenderer> app) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual bool OnBeforeNavigation(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
cef_navigation_type_t navigation_type,
|
||||
bool is_redirect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {}
|
||||
|
||||
virtual void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {}
|
||||
|
||||
virtual void OnUncaughtException(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) {}
|
||||
|
||||
virtual void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) {}
|
||||
|
||||
// Called when a process message is received. Return true if the message was
|
||||
// handled and should not be passed on to other handlers. Delegates
|
||||
// should check for unique message names to avoid interfering with each
|
||||
// other.
|
||||
virtual bool OnProcessMessageReceived(
|
||||
CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set<CefRefPtr<Delegate> > DelegateSet;
|
||||
|
||||
ClientAppRenderer();
|
||||
|
||||
private:
|
||||
// Creates all of the Delegate objects. Implemented by cefclient in
|
||||
// client_app_delegates_renderer.cc
|
||||
static void CreateDelegates(DelegateSet& delegates);
|
||||
|
||||
// CefApp methods.
|
||||
CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefRenderProcessHandler methods.
|
||||
void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
|
||||
void OnWebKitInitialized() OVERRIDE;
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
|
||||
bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
NavigationType navigation_type,
|
||||
bool is_redirect) OVERRIDE;
|
||||
void OnContextCreated(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
void OnContextReleased(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE;
|
||||
void OnUncaughtException(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context,
|
||||
CefRefPtr<CefV8Exception> exception,
|
||||
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
|
||||
void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) OVERRIDE;
|
||||
bool OnProcessMessageReceived(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Set of supported Delegates.
|
||||
DelegateSet delegates_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientAppRenderer);
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientAppRenderer);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
|
||||
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2012 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 "cefclient/renderer/client_renderer.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "include/cef_dom.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "include/wrapper/cef_message_router.h"
|
||||
|
||||
namespace client {
|
||||
namespace renderer {
|
||||
|
||||
namespace {
|
||||
|
||||
// Must match the value in client_handler.cc.
|
||||
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
|
||||
|
||||
class ClientRenderDelegate : public ClientAppRenderer::Delegate {
|
||||
public:
|
||||
ClientRenderDelegate()
|
||||
: last_node_is_editable_(false) {
|
||||
}
|
||||
|
||||
virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) OVERRIDE {
|
||||
// Create the renderer-side router for query handling.
|
||||
CefMessageRouterConfig config;
|
||||
message_router_ = CefMessageRouterRendererSide::Create(config);
|
||||
}
|
||||
|
||||
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE {
|
||||
message_router_->OnContextCreated(browser, frame, context);
|
||||
}
|
||||
|
||||
virtual void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE {
|
||||
message_router_->OnContextReleased(browser, frame, context);
|
||||
}
|
||||
|
||||
virtual void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefDOMNode> node) OVERRIDE {
|
||||
bool is_editable = (node.get() && node->IsEditable());
|
||||
if (is_editable != last_node_is_editable_) {
|
||||
// Notify the browser of the change in focused element type.
|
||||
last_node_is_editable_ = is_editable;
|
||||
CefRefPtr<CefProcessMessage> message =
|
||||
CefProcessMessage::Create(kFocusedNodeChangedMessage);
|
||||
message->GetArgumentList()->SetBool(0, is_editable);
|
||||
browser->SendProcessMessage(PID_BROWSER, message);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnProcessMessageReceived(
|
||||
CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) OVERRIDE {
|
||||
return message_router_->OnProcessMessageReceived(
|
||||
browser, source_process, message);
|
||||
}
|
||||
|
||||
private:
|
||||
bool last_node_is_editable_;
|
||||
|
||||
// Handles the renderer side of query routing.
|
||||
CefRefPtr<CefMessageRouterRendererSide> message_router_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ClientRenderDelegate);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new ClientRenderDelegate);
|
||||
}
|
||||
|
||||
} // namespace renderer
|
||||
} // namespace client
|
||||
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_RENDERER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_RENDERER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_base.h"
|
||||
#include "cefclient/renderer/client_app_renderer.h"
|
||||
|
||||
namespace client {
|
||||
namespace renderer {
|
||||
|
||||
// Create the renderer delegate. Called from client_app_delegates_renderer.cc.
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
|
||||
|
||||
} // namespace renderer
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_RENDERER_H_
|
||||
@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2012 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 "cefclient/renderer/performance_test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "cefclient/renderer/performance_test_setup.h"
|
||||
|
||||
namespace client {
|
||||
namespace performance_test {
|
||||
|
||||
// Use more interations for a Release build.
|
||||
#ifdef NDEBUG
|
||||
const int kDefaultIterations = 100000;
|
||||
#else
|
||||
const int kDefaultIterations = 10000;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
const char kGetPerfTests[] = "GetPerfTests";
|
||||
const char kRunPerfTest[] = "RunPerfTest";
|
||||
const char kPerfTestReturnValue[] = "PerfTestReturnValue";
|
||||
|
||||
class V8Handler : public CefV8Handler {
|
||||
public:
|
||||
V8Handler() {
|
||||
}
|
||||
|
||||
virtual bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) {
|
||||
if (name == kRunPerfTest) {
|
||||
if (arguments.size() == 1 && arguments[0]->IsString()) {
|
||||
// Run the specified perf test.
|
||||
bool found = false;
|
||||
|
||||
std::string test = arguments[0]->GetStringValue();
|
||||
for (int i = 0; i < kPerfTestsCount; ++i) {
|
||||
if (test == kPerfTests[i].name) {
|
||||
// Execute the test.
|
||||
int64 delta = kPerfTests[i].test(kPerfTests[i].iterations);
|
||||
|
||||
retval = CefV8Value::CreateInt(delta);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
std::string msg = "Unknown test: ";
|
||||
msg.append(test);
|
||||
exception = msg;
|
||||
}
|
||||
} else {
|
||||
exception = "Invalid function parameters";
|
||||
}
|
||||
} else if (name == kGetPerfTests) {
|
||||
// Retrieve the list of perf tests.
|
||||
retval = CefV8Value::CreateArray(kPerfTestsCount);
|
||||
for (int i = 0; i < kPerfTestsCount; ++i) {
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateArray(2);
|
||||
val->SetValue(0, CefV8Value::CreateString(kPerfTests[i].name));
|
||||
val->SetValue(1, CefV8Value::CreateUInt(kPerfTests[i].iterations));
|
||||
retval->SetValue(i, val);
|
||||
}
|
||||
} else if (name == kPerfTestReturnValue) {
|
||||
if (arguments.size() == 0) {
|
||||
retval = CefV8Value::CreateInt(1);
|
||||
} else if (arguments.size() == 1 && arguments[0]->IsInt()) {
|
||||
int32 type = arguments[0]->GetIntValue();
|
||||
CefTime date;
|
||||
switch (type) {
|
||||
case 0:
|
||||
retval = CefV8Value::CreateUndefined();
|
||||
break;
|
||||
case 1:
|
||||
retval = CefV8Value::CreateNull();
|
||||
break;
|
||||
case 2:
|
||||
retval = CefV8Value::CreateBool(true);
|
||||
break;
|
||||
case 3:
|
||||
retval = CefV8Value::CreateInt(1);
|
||||
break;
|
||||
case 4:
|
||||
retval = CefV8Value::CreateUInt(1);
|
||||
break;
|
||||
case 5:
|
||||
retval = CefV8Value::CreateDouble(1.234);
|
||||
break;
|
||||
case 6:
|
||||
date.Now();
|
||||
retval = CefV8Value::CreateDate(date);
|
||||
break;
|
||||
case 7:
|
||||
retval = CefV8Value::CreateString("Hello, world!");
|
||||
break;
|
||||
case 8:
|
||||
retval = CefV8Value::CreateObject(NULL);
|
||||
break;
|
||||
case 9:
|
||||
retval = CefV8Value::CreateArray(8);
|
||||
break;
|
||||
case 10:
|
||||
// retval = CefV8Value::CreateFunction(...);
|
||||
exception = "Not implemented";
|
||||
break;
|
||||
default:
|
||||
exception = "Not supported";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(V8Handler);
|
||||
};
|
||||
|
||||
// Handle bindings in the render process.
|
||||
class RenderDelegate : public ClientAppRenderer::Delegate {
|
||||
public:
|
||||
RenderDelegate() {
|
||||
}
|
||||
|
||||
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) OVERRIDE {
|
||||
CefRefPtr<CefV8Value> object = context->GetGlobal();
|
||||
|
||||
CefRefPtr<CefV8Handler> handler = new V8Handler();
|
||||
|
||||
// Bind test functions.
|
||||
object->SetValue(kGetPerfTests,
|
||||
CefV8Value::CreateFunction(kGetPerfTests, handler),
|
||||
V8_PROPERTY_ATTRIBUTE_READONLY);
|
||||
object->SetValue(kRunPerfTest,
|
||||
CefV8Value::CreateFunction(kRunPerfTest, handler),
|
||||
V8_PROPERTY_ATTRIBUTE_READONLY);
|
||||
object->SetValue(kPerfTestReturnValue,
|
||||
CefV8Value::CreateFunction(kPerfTestReturnValue, handler),
|
||||
V8_PROPERTY_ATTRIBUTE_READONLY);
|
||||
}
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(RenderDelegate);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new RenderDelegate);
|
||||
}
|
||||
|
||||
} // namespace performance_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "cefclient/renderer/client_app_renderer.h"
|
||||
|
||||
namespace client {
|
||||
namespace performance_test {
|
||||
|
||||
// Create the renderer delegate. Called from client_app_delegates_renderer.cc.
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
|
||||
|
||||
} // namespace performance_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_
|
||||
@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2012 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 CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_SETUP_H_
|
||||
#define CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_SETUP_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
|
||||
namespace client {
|
||||
namespace performance_test {
|
||||
|
||||
// Default number of iterations.
|
||||
extern const int kDefaultIterations;
|
||||
|
||||
// Test name.
|
||||
#define PERF_TEST_NAME(name) PerfTest##name
|
||||
|
||||
// Entry in test array.
|
||||
#define PERF_TEST_ENTRY_EX(name, iterations) \
|
||||
{ #name, PERF_TEST_NAME(name), iterations }
|
||||
#define PERF_TEST_ENTRY(name) PERF_TEST_ENTRY_EX(name, kDefaultIterations)
|
||||
|
||||
// Test function declaration.
|
||||
#define PERF_TEST_RESULT int64
|
||||
#define PERF_TEST_PARAM_ITERATIONS iterations
|
||||
#define PERF_TEST_PARAMS int PERF_TEST_PARAM_ITERATIONS
|
||||
#define PERF_TEST_FUNC(name) \
|
||||
PERF_TEST_RESULT PERF_TEST_NAME(name)(PERF_TEST_PARAMS)
|
||||
|
||||
// Typedef for test pointers.
|
||||
typedef PERF_TEST_RESULT(PerfTest(PERF_TEST_PARAMS));
|
||||
|
||||
class CefTimer {
|
||||
public:
|
||||
CefTimer() : running_(false) {
|
||||
}
|
||||
|
||||
bool IsRunning() { return running_; }
|
||||
|
||||
void Start() {
|
||||
DCHECK(!running_);
|
||||
running_ = true;
|
||||
start_.Now();
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
stop_.Now();
|
||||
DCHECK(running_);
|
||||
running_ = false;
|
||||
}
|
||||
|
||||
int64 Delta() {
|
||||
DCHECK(!running_);
|
||||
return start_.Delta(stop_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool running_;
|
||||
CefTime start_;
|
||||
CefTime stop_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefTimer);
|
||||
};
|
||||
|
||||
// Peform test iterations using a user-provided timing result variable.
|
||||
#define PERF_ITERATIONS_START_EX() \
|
||||
{ \
|
||||
CefTimer _timer; \
|
||||
_timer.Start(); \
|
||||
for (int _i = 0; _i < PERF_TEST_PARAM_ITERATIONS; ++_i) {
|
||||
|
||||
#define PERF_ITERATIONS_END_EX(result) \
|
||||
} \
|
||||
_timer.Stop(); \
|
||||
result = _timer.Delta(); \
|
||||
}
|
||||
|
||||
// Perform test iterations and return the timing result.
|
||||
#define PERF_ITERATIONS_START() \
|
||||
int64 _result = 0; \
|
||||
PERF_ITERATIONS_START_EX()
|
||||
|
||||
#define PERF_ITERATIONS_END() \
|
||||
PERF_ITERATIONS_END_EX(_result) \
|
||||
return _result;
|
||||
|
||||
// Perf test entry structure.
|
||||
struct PerfTestEntry {
|
||||
const char* name;
|
||||
PerfTest* test;
|
||||
int iterations;
|
||||
};
|
||||
|
||||
// Array of perf tests.
|
||||
extern const PerfTestEntry kPerfTests[];
|
||||
extern const int kPerfTestsCount;
|
||||
|
||||
} // namespace performance_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_
|
||||
@ -0,0 +1,330 @@
|
||||
// Copyright (c) 2012 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 "cefclient/renderer/performance_test.h"
|
||||
#include "cefclient/renderer/performance_test_setup.h"
|
||||
#include "include/cef_v8.h"
|
||||
|
||||
namespace client {
|
||||
namespace performance_test {
|
||||
|
||||
namespace {
|
||||
|
||||
// Test function implementations.
|
||||
|
||||
PERF_TEST_FUNC(V8NullCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateNull();
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8BoolCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateBool(true);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8IntCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateInt(-5);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8UIntCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateUInt(10);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8DoubleCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateDouble(12.432);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8DateCreate) {
|
||||
static cef_time_t time = {2012, 1, 0, 1};
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(time);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8StringCreate) {
|
||||
CefString str = "test string";
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateString(str);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ArrayCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateArray(1);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ArraySetValue) {
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> array = CefV8Value::CreateArray(1);
|
||||
array->SetValue(0, val);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
array->SetValue(0, val);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ArrayGetValue) {
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> array = CefV8Value::CreateArray(1);
|
||||
array->SetValue(0, val);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> ret = array->GetValue(0);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8FunctionCreate) {
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
virtual bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE { return false; }
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Handler> handler = new Handler();
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateFunction(name, handler);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8FunctionExecute) {
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
virtual bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE { return true; }
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Handler> handler = new Handler();
|
||||
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(name, handler);
|
||||
CefRefPtr<CefV8Value> obj = CefV8Context::GetCurrentContext()->GetGlobal();
|
||||
CefV8ValueList args;
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
func->ExecuteFunction(obj, args);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8FunctionExecuteWithContext) {
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
virtual bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE { return true; }
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Handler> handler = new Handler();
|
||||
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(name, handler);
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
CefRefPtr<CefV8Value> obj = context->GetGlobal();
|
||||
CefV8ValueList args;
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
func->ExecuteFunctionWithContext(context, obj, args);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectCreate) {
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectCreateWithAccessor) {
|
||||
class Accessor : public CefV8Accessor {
|
||||
public:
|
||||
Accessor() {}
|
||||
virtual bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
virtual bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value,
|
||||
CefString& exception) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
IMPLEMENT_REFCOUNTING(Accessor);
|
||||
};
|
||||
|
||||
CefRefPtr<CefV8Accessor> accessor = new Accessor();
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(accessor);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectSetValue) {
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectGetValue) {
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> ret = obj->GetValue(name);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectSetValueWithAccessor) {
|
||||
class Accessor : public CefV8Accessor {
|
||||
public:
|
||||
Accessor() {}
|
||||
virtual bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
virtual bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value,
|
||||
CefString& exception) OVERRIDE {
|
||||
val_ = value;
|
||||
return true;
|
||||
}
|
||||
CefRefPtr<CefV8Value> val_;
|
||||
IMPLEMENT_REFCOUNTING(Accessor);
|
||||
};
|
||||
|
||||
CefRefPtr<CefV8Accessor> accessor = new Accessor();
|
||||
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
|
||||
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ObjectGetValueWithAccessor) {
|
||||
class Accessor : public CefV8Accessor {
|
||||
public:
|
||||
Accessor() : val_(CefV8Value::CreateBool(true)) {}
|
||||
virtual bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE {
|
||||
retval = val_;
|
||||
return true;
|
||||
}
|
||||
virtual bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value,
|
||||
CefString& exception) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
CefRefPtr<CefV8Value> val_;
|
||||
IMPLEMENT_REFCOUNTING(Accessor);
|
||||
};
|
||||
|
||||
CefRefPtr<CefV8Accessor> accessor = new Accessor();
|
||||
|
||||
CefString name = "name";
|
||||
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
|
||||
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
|
||||
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
CefRefPtr<CefV8Value> ret = obj->GetValue(name);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ContextEnterExit) {
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
context->Enter();
|
||||
context->Exit();
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ContextEval) {
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
CefString jsCode = "var i = 0;";
|
||||
CefRefPtr<CefV8Value> retval;
|
||||
CefRefPtr<CefV8Exception> exception;
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
context->Eval(jsCode, retval, exception);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// Test function entries.
|
||||
|
||||
const PerfTestEntry kPerfTests[] = {
|
||||
PERF_TEST_ENTRY(V8NullCreate),
|
||||
PERF_TEST_ENTRY(V8BoolCreate),
|
||||
PERF_TEST_ENTRY(V8IntCreate),
|
||||
PERF_TEST_ENTRY(V8UIntCreate),
|
||||
PERF_TEST_ENTRY(V8DoubleCreate),
|
||||
PERF_TEST_ENTRY(V8DateCreate),
|
||||
PERF_TEST_ENTRY(V8StringCreate),
|
||||
PERF_TEST_ENTRY(V8ArrayCreate),
|
||||
PERF_TEST_ENTRY(V8ArraySetValue),
|
||||
PERF_TEST_ENTRY(V8ArrayGetValue),
|
||||
PERF_TEST_ENTRY(V8FunctionCreate),
|
||||
PERF_TEST_ENTRY(V8FunctionExecute),
|
||||
PERF_TEST_ENTRY(V8FunctionExecuteWithContext),
|
||||
PERF_TEST_ENTRY(V8ObjectCreate),
|
||||
PERF_TEST_ENTRY(V8ObjectCreateWithAccessor),
|
||||
PERF_TEST_ENTRY(V8ObjectSetValue),
|
||||
PERF_TEST_ENTRY(V8ObjectGetValue),
|
||||
PERF_TEST_ENTRY(V8ObjectSetValueWithAccessor),
|
||||
PERF_TEST_ENTRY(V8ObjectGetValueWithAccessor),
|
||||
PERF_TEST_ENTRY(V8ContextEnterExit),
|
||||
PERF_TEST_ENTRY(V8ContextEval),
|
||||
};
|
||||
|
||||
const int kPerfTestsCount = (sizeof(kPerfTests) / sizeof(kPerfTests[0]));
|
||||
|
||||
} // namespace performance_test
|
||||
} // namespace client
|
||||
@ -0,0 +1,28 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Binding Test</title>
|
||||
<script language="JavaScript">
|
||||
|
||||
// Send a query to the browser process.
|
||||
function sendMessage() {
|
||||
// Results in a call to the OnQuery method in binding_test.cpp
|
||||
window.cefQuery({
|
||||
request: 'BindingTest:' + document.getElementById("message").value,
|
||||
onSuccess: function(response) {
|
||||
document.getElementById('result').value = 'Response: '+response;
|
||||
},
|
||||
onFailure: function(error_code, error_message) {}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<form>
|
||||
Message: <input type="text" id="message" value="My Message">
|
||||
<br/><input type="button" onclick="sendMessage();" value="Send Message">
|
||||
<br/>You should see the reverse of your message below:
|
||||
<br/><textarea rows="10" cols="40" id="result"></textarea>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,65 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Dialog Test</title>
|
||||
<script>
|
||||
function show_alert() {
|
||||
alert("I am an alert box!");
|
||||
}
|
||||
|
||||
function show_confirm() {
|
||||
var r = confirm("Press a button");
|
||||
var msg = r ? "You pressed OK!" : "You pressed Cancel!";
|
||||
document.getElementById('cm').innerText = msg;
|
||||
}
|
||||
|
||||
function show_prompt() {
|
||||
var name = prompt("Please enter your name" ,"Harry Potter");
|
||||
if (name != null && name != "")
|
||||
document.getElementById('pm').innerText = "Hello " + name + "!";
|
||||
}
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
return 'This is an onbeforeunload message.';
|
||||
}
|
||||
|
||||
function update_time() {
|
||||
document.getElementById('time').innerText = new Date().toLocaleString();
|
||||
}
|
||||
|
||||
function setup() {
|
||||
update_time();
|
||||
setInterval(update_time, 1000);
|
||||
}
|
||||
|
||||
function show_file_dialog(element, test) {
|
||||
var message = 'DialogTest.' + test;
|
||||
var target = document.getElementById(element);
|
||||
|
||||
// Results in a call to the OnQuery method in dialog_test.cpp
|
||||
window.cefQuery({
|
||||
request: message,
|
||||
onSuccess: function(response) {
|
||||
target.innerText = response;
|
||||
},
|
||||
onFailure: function(error_code, error_message) {}
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('load', setup, false);
|
||||
</script>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<form>
|
||||
Click a button to show the associated dialog type.
|
||||
<br/><input type="button" onclick="show_alert();" value="Show Alert">
|
||||
<br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
|
||||
<br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
|
||||
<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
|
||||
<br/><input type="button" onclick="show_file_dialog('fo', 'FileOpen');" value="Show File Open"> <span id="fo"></span>
|
||||
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open Multiple"> <span id="fom"></span>
|
||||
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder"> <span id="fof"></span>
|
||||
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save"> <span id="fs"></span>
|
||||
<p id="time"></p>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,24 @@
|
||||
<html>
|
||||
<body bgcolor="white">
|
||||
<script language="JavaScript">
|
||||
var val = window.localStorage.getItem('val');
|
||||
function addLine() {
|
||||
if(val == null)
|
||||
val = '<br/>One Line.';
|
||||
else
|
||||
val += '<br/>Another Line.';
|
||||
window.localStorage.setItem('val', val);
|
||||
document.getElementById('out').innerHTML = val;
|
||||
}
|
||||
</script>
|
||||
Click the "Add Line" button to add a line or the "Clear" button to clear.<br/>
|
||||
This data will persist across sessions if a cache path was specified.<br/>
|
||||
<input type="button" value="Add Line" onClick="addLine();"/>
|
||||
<input type="button" value="Clear" onClick="window.localStorage.removeItem('val'); window.location.reload();"/>
|
||||
<div id="out"></div>
|
||||
<script language="JavaScript">
|
||||
if(val != null)
|
||||
document.getElementById('out').innerHTML = val;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,109 @@
|
||||
<html>
|
||||
<head><title>OSR Test</title></head>
|
||||
<style>
|
||||
.red_hover:hover {color:red;}
|
||||
#li { width: 530px; }
|
||||
body {background:rgba(255, 0, 0, 0.5); }
|
||||
input {-webkit-appearance: none; }
|
||||
#LI11select {width: 75px;}
|
||||
.dropdiv {
|
||||
width:50px;
|
||||
height:50px;
|
||||
border:1px solid #aaaaaa;
|
||||
float: left;
|
||||
}
|
||||
#dragdiv {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: green;
|
||||
margin: 10px;
|
||||
}
|
||||
#draghere {
|
||||
position: relative;
|
||||
z-index: -1;
|
||||
top: 7px;
|
||||
left: 7px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function getElement(id) { return document.getElementById(id); }
|
||||
function makeH1Red() { getElement('LI00').style.color='red'; }
|
||||
function makeH1Black() { getElement('LI00').style.color='black'; }
|
||||
function navigate() { location.href='?k='+getElement('editbox').value; }
|
||||
function load() { var select = document.getElementById('LI11select');
|
||||
for (var i = 1; i < 21; i++)
|
||||
select.options.add(new Option('Option ' + i, i));
|
||||
}
|
||||
|
||||
function onEventTest(event) {
|
||||
var param = 'osr' + event.type;
|
||||
|
||||
if (event.type == "click")
|
||||
param += event.button;
|
||||
|
||||
// Results in a call to the OnQuery method in os_rendering_unittest.cc.
|
||||
if (window.testQuery)
|
||||
window.testQuery({request: param});
|
||||
}
|
||||
|
||||
function allowDrop(ev) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
function drag(ev) {
|
||||
ev.dataTransfer.setData("Text",ev.target.id);
|
||||
}
|
||||
|
||||
function drop(ev) {
|
||||
var data=ev.dataTransfer.getData("Text");
|
||||
ev.target.innerHTML = '';
|
||||
var dragged = document.getElementById(data);
|
||||
dragged.setAttribute('draggable', 'false');
|
||||
ev.target.appendChild(dragged);
|
||||
if (window.testQuery)
|
||||
window.testQuery({request: "osrdrop"});
|
||||
}
|
||||
</script>
|
||||
<body onfocus='onEventTest(event)' onblur='onEventTest(event)' onload='load();'>
|
||||
<h1 id='LI00' onclick="onEventTest(event)">
|
||||
OSR Testing h1 - Focus and blur
|
||||
<select id='LI11select'>
|
||||
<option value='0'>Default</option>
|
||||
</select>
|
||||
this page and will get this red black
|
||||
</h1>
|
||||
<ol>
|
||||
<li id='LI01'>OnPaint should be called each time a page loads</li>
|
||||
<li id='LI02' style='cursor:pointer;'><span>Move mouse
|
||||
to require an OnCursorChange call</span></li>
|
||||
<li id='LI03' onmousemove="onEventTest(event)"><span>Hover will color this with
|
||||
red. Will trigger OnPaint once on enter and once on leave</span></li>
|
||||
<li id='LI04'>Right clicking will show contextual menu and will request
|
||||
GetScreenPoint</li>
|
||||
<li id='LI05'>IsWindowRenderingDisabled should be true</li>
|
||||
<li id='LI06'>WasResized should trigger full repaint if size changes.
|
||||
</li>
|
||||
<li id='LI07'>Invalidate should trigger OnPaint once</li>
|
||||
<li id='LI08'>Click and write here with SendKeyEvent to trigger repaints:
|
||||
<input id='editbox' type='text' value='' size="5"></li>
|
||||
<li id='LI09'>Click here with SendMouseClickEvent to navigate:
|
||||
<input id='btnnavigate' type='button' onclick='navigate()'
|
||||
value='Click here to navigate' id='editbox' /></li>
|
||||
<li id='LI10' title='EXPECTED_TOOLTIP'>Mouse over this element will
|
||||
trigger show a tooltip</li>
|
||||
</ol>
|
||||
<div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">
|
||||
<span id="draghere">Drag here</span>
|
||||
</div>
|
||||
<div class="dropdiv">
|
||||
<div id="dragdiv" draggable="true" ondragstart="drag(event)"></div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,35 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Other Tests</title>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<h3>Various other internal and external tests.</h3>
|
||||
<ul>
|
||||
<li><a href="http://mudcu.be/labs/JS1k/BreathingGalaxies.html">Accelerated 2D Canvas</a></li>
|
||||
<li><a href="http://webkit.org/blog-files/3d-transforms/poster-circle.html">Accelerated Layers</a></li>
|
||||
<li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
|
||||
<li><a href="http://tests/dialogs">Dialogs</a></li>
|
||||
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
|
||||
<li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a></li>
|
||||
<li><a href="http://html5demos.com/geo">Geolocation</a></li>
|
||||
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
|
||||
<li><a href="http://www.youtube.com/watch?v=siOHh0uzcuY&html5=True">HTML5 Video</a></li>
|
||||
<li><a href="http://tests/binding">JavaScript Binding</a></li>
|
||||
<li><a href="http://tests/performance">JavaScript Performance Tests</a></li>
|
||||
<li><a href="http://tests/performance2">JavaScript Performance (2) Tests</a></li>
|
||||
<li><a href="http://tests/window">JavaScript Window Manipulation</a></li>
|
||||
<li><a href="http://tests/localstorage">Local Storage</a></li>
|
||||
<li><a href="http://tests/pdf.pdf">PDF Viewer direct</a></li>
|
||||
<li><a href="http://tests/pdf">PDF Viewer iframe</a></li>
|
||||
<li><a href="http://mrdoob.com/lab/javascript/requestanimationframe/">requestAnimationFrame</a></li>
|
||||
<li><a href="client://tests/handler.html">Scheme Handler</a></li>
|
||||
<li><a href="https://www.google.com/intl/en/chrome/demos/speech.html">Speech Input</a> - requires "enable-speech-input" flag</li>
|
||||
<li><a href="http://tests/transparency">Transparency</a></li>
|
||||
<li><a href="http://webglsamples.googlecode.com/hg/field/field.html">WebGL</a></li>
|
||||
<li><a href="http://apprtc.appspot.com/">WebRTC</a> - requires "enable-media-stream" flag</li>
|
||||
<li><a href="http://tests/urlrequest">CefURLRequest</a></li>
|
||||
<li><a href="http://tests/xmlhttprequest">XMLHttpRequest</a></li>
|
||||
<li><a href="javascript:window.print();">Print this page with "javascript:window.print();"</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>PDF Test</title>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<iframe src="pdf.pdf" width="500" height="500"></iframe>
|
||||
<iframe src="pdf.pdf" width="500" height="500"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
@ -0,0 +1,293 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Performance Tests</title>
|
||||
<style>
|
||||
body { font-family: Tahoma, Serif; font-size: 9pt; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<h1>Performance Tests</h1>
|
||||
<input type="button" value="Run Tests" onClick="run();" id="run"/> Filter: <input type="text" size="50" id="filters"/>
|
||||
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
|
||||
|
||||
<div style="padding-top:10px; padding-bottom:10px">
|
||||
<table id="resultTable" border="1" cellspacing="1" cellpadding="4">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Iterations per Run</td>
|
||||
<td>Avg (ms)</td>
|
||||
<td>Min (ms)</td>
|
||||
<td>Max (ms)</td>
|
||||
<td>StdDev (ms)</td>
|
||||
<td>Runs (ms)</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- result rows here -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<hr width="80%">
|
||||
|
||||
Result 1: <input type="text" size="100" id="result1"/>
|
||||
<br/>Result 2: <input type="text" size="100" id="result2"/>
|
||||
<br/><input type="button" value="Compare" onClick="compare();" id="compare"/>
|
||||
|
||||
<div style="padding-top:10px; padding-bottom:10px">
|
||||
<table id="compareTable" border="1" cellspacing="1" cellpadding="4">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Result 1 Avg (ms)</td>
|
||||
<td>Result 2 Avg (ms)</td>
|
||||
<td>% Diff</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- result rows here -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function run() {
|
||||
var runElement = document.getElementById("run");
|
||||
var filtersElement = document.getElementById("filters");
|
||||
var compareElement = document.getElementById("compare");
|
||||
var result1Element = document.getElementById("result1");
|
||||
var result2Element = document.getElementById("result2");
|
||||
|
||||
// Number of runs for each test.
|
||||
var testRuns = 10;
|
||||
|
||||
// Delay between test runs.
|
||||
var runDelay = 0;
|
||||
|
||||
// Retrieve the list of all tests.
|
||||
var allTests = window.GetPerfTests();
|
||||
|
||||
// Populated with the list of tests that will be run.
|
||||
var tests = [];
|
||||
var currentTest = 0;
|
||||
|
||||
var testList = filtersElement.value.trim();
|
||||
if (testList.length > 0) {
|
||||
// Include or exclude specific tests.
|
||||
var included = [];
|
||||
var excluded = [];
|
||||
|
||||
var testNames = testList.split(",");
|
||||
|
||||
// Identify included and excluded tests.
|
||||
for (i = 0; i < testNames.length; ++i) {
|
||||
var testName = testNames[i].trim();
|
||||
if (testName[0] == '-') {
|
||||
// Exclude the test.
|
||||
excluded.push(testName.substr(1));
|
||||
} else {
|
||||
// Include the test.
|
||||
included.push(testName);
|
||||
}
|
||||
}
|
||||
|
||||
if (included.length > 0) {
|
||||
// Only use the included tests.
|
||||
for (i = 0; i < allTests.length; ++i) {
|
||||
var test = allTests[i];
|
||||
var testName = test[0];
|
||||
if (included.indexOf(testName) >= 0)
|
||||
tests.push(test);
|
||||
}
|
||||
} else if (excluded.length > 0) {
|
||||
// Use all tests except the excluded tests.
|
||||
for (i = 0; i < allTests.length; ++i) {
|
||||
var test = allTests[i];
|
||||
var testName = test[0];
|
||||
if (excluded.indexOf(testName) < 0)
|
||||
tests.push(test);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Run all tests.
|
||||
tests = allTests;
|
||||
}
|
||||
|
||||
function updateStatusComplete() {
|
||||
var statusBox = document.getElementById("statusBox");
|
||||
statusBox.innerText = 'All tests completed.';
|
||||
|
||||
runElement.disabled = false;
|
||||
filtersElement.disabled = false;
|
||||
result1Element.disabled = false;
|
||||
result2Element.disabled = false;
|
||||
compareElement.disabled = false;
|
||||
}
|
||||
|
||||
function updateStatus(test) {
|
||||
var statusBox = document.getElementById("statusBox");
|
||||
var progressBox = document.getElementById("progressBox");
|
||||
|
||||
if (test.run >= test.totalRuns) {
|
||||
statusBox.innerText = test.name + " completed.";
|
||||
progressBox.style.display = 'none';
|
||||
} else {
|
||||
statusBox.innerText = test.name + " (" + test.run + "/" + test.totalRuns + ")";
|
||||
progressBox.value = (test.run / test.totalRuns);
|
||||
progressBox.style.display = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
function appendResult(test) {
|
||||
var e = document.getElementById("resultTable");
|
||||
|
||||
// Calculate the average.
|
||||
var avg = test.total / test.totalRuns;
|
||||
|
||||
// Calculate the standard deviation.
|
||||
var sqsum = 0;
|
||||
for (i = 0; i < test.results.length; ++i) {
|
||||
var diff = test.results[i] - avg;
|
||||
sqsum += diff * diff;
|
||||
}
|
||||
var stddev = Math.round(Math.sqrt(sqsum / test.totalRuns) * 100.0) / 100.0;
|
||||
|
||||
e.insertAdjacentHTML("beforeEnd", [
|
||||
"<tr>",
|
||||
"<td>", test.name, "</td>",
|
||||
"<td>", test.iterations, "</td>",
|
||||
"<td>", avg, "</td>",
|
||||
"<td>", test.min, "</td>",
|
||||
"<td>", test.max, "</td>",
|
||||
"<td>", stddev, "</td>",
|
||||
"<td>", test.results.join(", "), "</td>",
|
||||
"<tr>"
|
||||
].join(""));
|
||||
|
||||
if (result1Element.value.length > 0)
|
||||
result1Element.value += ",";
|
||||
result1Element.value += test.name + "=" + avg;
|
||||
}
|
||||
|
||||
// Execute the test function.
|
||||
function execTestFunc(name) {
|
||||
return window.RunPerfTest(name);
|
||||
}
|
||||
|
||||
// Schedule the next test.
|
||||
function nextTest(test) {
|
||||
appendResult(test);
|
||||
currentTest++;
|
||||
runTest();
|
||||
}
|
||||
|
||||
// Schedule the next step for the current test.
|
||||
function nextTestStep(test) {
|
||||
setTimeout(function () { execTest(test); }, runDelay);
|
||||
}
|
||||
|
||||
// Perform the next step for the current test.
|
||||
function execTest(test) {
|
||||
updateStatus(test);
|
||||
|
||||
if (!test.warmedUp) {
|
||||
execTestFunc(test.name);
|
||||
test.warmedUp = true;
|
||||
return nextTestStep(test);
|
||||
}
|
||||
|
||||
if (test.run >= test.totalRuns)
|
||||
return nextTest(test);
|
||||
|
||||
var elapsed = execTestFunc(test.name);
|
||||
test.results.push(elapsed);
|
||||
|
||||
test.total += elapsed;
|
||||
if (!test.min) test.min = elapsed;
|
||||
else if (test.min > elapsed) test.min = elapsed;
|
||||
if (!test.max) test.max = elapsed;
|
||||
else if (test.max < elapsed) test.max = elapsed;
|
||||
|
||||
test.run++;
|
||||
|
||||
return nextTestStep(test);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
if (currentTest == tests.length) {
|
||||
updateStatusComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = {
|
||||
name: tests[currentTest][0],
|
||||
iterations: tests[currentTest][1],
|
||||
warmedUp: false,
|
||||
total: 0,
|
||||
totalRuns: testRuns,
|
||||
run: 0,
|
||||
results: []
|
||||
};
|
||||
setTimeout(function () { execTest(test); }, runDelay);
|
||||
}
|
||||
|
||||
// Schedule the first test.
|
||||
if (tests.length > 0) {
|
||||
runElement.disabled = true;
|
||||
filtersElement.disabled = true;
|
||||
result1Element.value = "";
|
||||
result1Element.disabled = true;
|
||||
result2Element.disabled = true;
|
||||
compareElement.disabled = true;
|
||||
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function compare() {
|
||||
var result1 = document.getElementById("result1").value.trim();
|
||||
var result2 = document.getElementById("result2").value.trim();
|
||||
|
||||
if (result1.length == 0 || result2.length == 0)
|
||||
return;
|
||||
|
||||
var r1values = result1.split(",");
|
||||
var r2values = result2.split(",");
|
||||
for (i = 0; i < r1values.length; ++i) {
|
||||
var r1parts = r1values[i].split("=");
|
||||
var r1name = r1parts[0].trim();
|
||||
var r1val = r1parts[1].trim();
|
||||
|
||||
for (x = 0; x < r2values.length; ++x) {
|
||||
var r2parts = r2values[x].split("=");
|
||||
var r2name = r2parts[0].trim();
|
||||
var r2val = r2parts[1].trim();
|
||||
|
||||
if (r2name == r1name) {
|
||||
appendResult(r1name, r1val, r2val);
|
||||
|
||||
// Remove the matching index.
|
||||
r2values.splice(x, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function appendResult(name, r1val, r2val) {
|
||||
var e = document.getElementById("compareTable");
|
||||
|
||||
// Calculate the percent difference.
|
||||
var diff = Math.round(((r2val - r1val) / r1val) * 10000.0) / 100.0;
|
||||
|
||||
e.insertAdjacentHTML("beforeEnd", [
|
||||
"<tr>",
|
||||
"<td>", name, "</td>",
|
||||
"<td>", r1val, "</td>",
|
||||
"<td>", r2val, "</td>",
|
||||
"<td>", diff, "</td>",
|
||||
"<tr>"
|
||||
].join(""));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,442 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Performance Tests (2)</title>
|
||||
<style>
|
||||
body { font-family: Tahoma, Serif; font-size: 9pt; }
|
||||
|
||||
.left { text-align: left; }
|
||||
.right { text-align: right; }
|
||||
.center { text-align: center; }
|
||||
|
||||
table.resultTable
|
||||
{
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
empty-cells: show;
|
||||
width: 100%;
|
||||
}
|
||||
table.resultTable td
|
||||
{
|
||||
padding: 2px 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
table.resultTable > thead > tr
|
||||
{
|
||||
font-weight: bold;
|
||||
background: lightblue;
|
||||
}
|
||||
table.resultTable > tbody > tr:nth-child(odd)
|
||||
{
|
||||
background: white;
|
||||
}
|
||||
table.resultTable > tbody > tr:nth-child(even)
|
||||
{
|
||||
background: lightgray;
|
||||
}
|
||||
|
||||
.hide { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<h1>Performance Tests (2)</h1>
|
||||
|
||||
<form id="sForm" onsubmit="runTestSuite();return false">
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">Settings:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">Iterations:</td>
|
||||
<td><input id="sIterations" type="text" value="1000" required pattern="[0-9]+" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">Samples:</td>
|
||||
<td><input id="sSamples" type="text" value="100" required pattern="[0-9]+" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right">Mode:</td>
|
||||
<td><input id="sAsync" name="sMode" type="radio" value="async" checked>Asynchronous</input>
|
||||
<input id="sSync" name="sMode" type="radio" value="sync">Synchronous</input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><button type="submit" id="sRun" autofocus>Run!</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
|
||||
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
|
||||
|
||||
<div style="padding-top:10px; padding-bottom:10px">
|
||||
<table id="resultTable" class="resultTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="center" style="width:1%">Enabled</td>
|
||||
<td class="center" style="width:10%">Name</td>
|
||||
<td class="center" style="width:5%">Samples x Iterations</td>
|
||||
<td class="center" style="width:5%">Min, ms</td>
|
||||
<td class="center" style="width:5%">Avg, ms</td>
|
||||
<td class="center" style="width:5%">Max, ms</td>
|
||||
<td class="center" style="width:5%">Average calls/sec</td>
|
||||
<td class="center" style="width:5%">Measuring Inacurracy</td>
|
||||
<td class="center hide" style="width:5%">Memory, MB</td>
|
||||
<td class="center hide" style="width:5%">Memory delta, MB</td>
|
||||
<td class="center" style="width:55%">Description</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- result rows here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
function getPrivateWorkingSet() {
|
||||
return 0; // TODO: window.PerfTestGetPrivateWorkingSet();
|
||||
}
|
||||
|
||||
var disableWarmUp = true;
|
||||
|
||||
var asyncExecution = true;
|
||||
var testIterations = 1000;
|
||||
var totalSamples = 100;
|
||||
var sampleDelay = 0;
|
||||
|
||||
var collectSamples = false;
|
||||
|
||||
var tests = [];
|
||||
var testIndex = -1;
|
||||
|
||||
function execTestFunc(test) {
|
||||
try {
|
||||
var begin = new Date();
|
||||
test.func(test.totalIterations);
|
||||
var end = new Date();
|
||||
return (end - begin);
|
||||
} catch (e) {
|
||||
test.error = e.toString();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function execTest(test) {
|
||||
if (disableWarmUp) { test.warmedUp = true; }
|
||||
|
||||
function nextStep() {
|
||||
if (asyncExecution) {
|
||||
setTimeout(function () { execTest(test); }, sampleDelay);
|
||||
} else {
|
||||
execTest(test);
|
||||
}
|
||||
}
|
||||
|
||||
function nextTest() {
|
||||
updateStatus(test);
|
||||
appendResult(test);
|
||||
|
||||
return execNextTest();
|
||||
}
|
||||
|
||||
updateStatus(test);
|
||||
if (!test.warmedUp) {
|
||||
execTestFunc(test);
|
||||
if (!test.error) {
|
||||
test.warmedUp = true;
|
||||
test.beginMemory = getPrivateWorkingSet();
|
||||
return nextStep();
|
||||
} else {
|
||||
return nextTest();
|
||||
}
|
||||
}
|
||||
|
||||
if (test.sample >= test.totalSamples) {
|
||||
test.avg = test.total / test.totalSamples;
|
||||
test.endMemory = getPrivateWorkingSet();
|
||||
return nextTest();
|
||||
}
|
||||
|
||||
if (test.skipped) return nextTest();
|
||||
|
||||
var elapsed = execTestFunc(test);
|
||||
if (!test.error) {
|
||||
test.total += elapsed;
|
||||
if (!test.min) test.min = elapsed;
|
||||
else if (test.min > elapsed) test.min = elapsed;
|
||||
if (!test.max) test.max = elapsed;
|
||||
else if (test.max < elapsed) test.max = elapsed;
|
||||
if (collectSamples) {
|
||||
test.results.push(elapsed);
|
||||
}
|
||||
test.sample++;
|
||||
return nextStep();
|
||||
} else {
|
||||
return nextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatus(test) {
|
||||
var statusBox = document.getElementById("statusBox");
|
||||
var progressBox = document.getElementById("progressBox");
|
||||
|
||||
if (test.skipped || test.error || test.sample >= test.totalSamples) {
|
||||
statusBox.innerText = "";
|
||||
progressBox.style.display = "none";
|
||||
} else {
|
||||
statusBox.innerText = (testIndex + 1) + "/" + tests.length + ": " + test.name + " (" + test.sample + "/" + test.totalSamples + ")";
|
||||
progressBox.value = (test.sample / test.totalSamples);
|
||||
progressBox.style.display = "inline";
|
||||
}
|
||||
}
|
||||
|
||||
function appendResult(test) {
|
||||
if (test.name == "warmup") return;
|
||||
|
||||
var id = "testResultRow_" + test.index;
|
||||
|
||||
var nearBound = (test.max - test.avg) < (test.avg - test.min) ? test.max : test.min;
|
||||
var memoryDelta = test.endMemory - test.beginMemory;
|
||||
if (memoryDelta < 0) memoryDelta = "-" + Math.abs(memoryDelta).toFixed(2);
|
||||
else memoryDelta = "+" + Math.abs(memoryDelta).toFixed(2);
|
||||
|
||||
var markup = ["<tr id='" + id + "'>",
|
||||
"<td class='left'><input type='checkbox' id='test_enabled_", test.index ,"' ", (!test.skipped ? "checked" : "") ," /></td>",
|
||||
"<td class='left'>", test.name, "</td>",
|
||||
"<td class='right'>", test.totalSamples, "x", test.totalIterations, "</td>",
|
||||
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.min.toFixed(2), "</td>",
|
||||
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.avg.toFixed(2), "</td>",
|
||||
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.max.toFixed(2), "</td>",
|
||||
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : (test.totalIterations * 1000 / test.avg).toFixed(2), "</td>",
|
||||
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : ("± " + (Math.abs(test.avg - nearBound) / (test.avg) * (100)).toFixed(2) + "%"), "</td>",
|
||||
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : test.endMemory.toFixed(2), "</td>",
|
||||
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : memoryDelta, "</td>",
|
||||
"<td class='left'>", test.description, test.error ? (test.description ? "<br/>" : "") + "<span style='color:red'>" + test.error + "</span>" : "", "</td>",
|
||||
"</tr>"
|
||||
].join("");
|
||||
// test.results.join(", "), "<br/>",
|
||||
|
||||
var row = document.getElementById(id);
|
||||
if (row) {
|
||||
row.outerHTML = markup;
|
||||
} else {
|
||||
var tbody = document.getElementById("resultTable").tBodies[0];
|
||||
tbody.insertAdjacentHTML("beforeEnd", markup);
|
||||
}
|
||||
}
|
||||
|
||||
function prepareQueuedTests() {
|
||||
testIndex = -1;
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
test.index = i;
|
||||
test.prepared = false;
|
||||
test.warmedUp = false;
|
||||
test.sample = 0;
|
||||
test.total = 0;
|
||||
test.results = [];
|
||||
test.error = false;
|
||||
test.min = null;
|
||||
test.avg = null;
|
||||
test.max = null;
|
||||
test.beginMemory = null;
|
||||
test.endMemory = null;
|
||||
test.totalIterations = parseInt(testIterations / test.complex);
|
||||
test.totalSamples = parseInt(totalSamples / test.complex);
|
||||
|
||||
var skipElement = document.getElementById('test_enabled_' + test.index);
|
||||
test.skipped = skipElement ? !skipElement.checked : (test.skipped || false);
|
||||
|
||||
if (test.totalIterations <= 0) test.totalIterations = 1;
|
||||
if (test.totalSamples <= 0) test.totalSamples = 1;
|
||||
|
||||
appendResult(test);
|
||||
test.prepared = true;
|
||||
}
|
||||
}
|
||||
|
||||
function queueTest(func, name, description) {
|
||||
var test;
|
||||
if (typeof func === "function") {
|
||||
test = {
|
||||
name: name,
|
||||
func: func,
|
||||
description: description
|
||||
};
|
||||
} else {
|
||||
test = func;
|
||||
}
|
||||
test.warmedUp = false;
|
||||
test.complex = test.complex || 1;
|
||||
tests.push(test);
|
||||
}
|
||||
|
||||
function execNextTest() {
|
||||
testIndex++;
|
||||
if (tests.length <= testIndex) {
|
||||
return testSuiteFinished();
|
||||
} else {
|
||||
return execTest(tests[testIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
function execQueuedTests() {
|
||||
prepareQueuedTests();
|
||||
execNextTest();
|
||||
}
|
||||
|
||||
function setSettingsState(disabled) {
|
||||
document.getElementById('sIterations').disabled = disabled;
|
||||
document.getElementById('sSamples').disabled = disabled;
|
||||
document.getElementById('sAsync').disabled = disabled;
|
||||
document.getElementById('sSync').disabled = disabled;
|
||||
document.getElementById('sRun').disabled = disabled;
|
||||
}
|
||||
|
||||
function testSuiteFinished() {
|
||||
setSettingsState(false);
|
||||
}
|
||||
|
||||
window.runTestSuite = function () {
|
||||
setSettingsState(true);
|
||||
|
||||
testIterations = parseInt(document.getElementById('sIterations').value);
|
||||
totalSamples = parseInt(document.getElementById('sSamples').value);
|
||||
asyncExecution = document.getElementById('sAsync').checked;
|
||||
|
||||
setTimeout(execQueuedTests, 0);
|
||||
}
|
||||
|
||||
setTimeout(prepareQueuedTests, 0);
|
||||
|
||||
// Test queue.
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue Default",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue();
|
||||
}
|
||||
},
|
||||
description: "No arguments, returns int32 value.",
|
||||
skipped: true,
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (0, Undefined)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(0);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns undefined value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (1, Null)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(1);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns null value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (2, Bool)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(2);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns bool value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (3, Int)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(3);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns int value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (4, UInt)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(4);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns uint value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (5, Double)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(5);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns double value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (6, Date)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(6);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns date value.",
|
||||
skipped: true,
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (7, String)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(7);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns string value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (8, Object)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(8);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns object value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (9, Array)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(9);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns array value."
|
||||
});
|
||||
|
||||
queueTest({
|
||||
name: "PerfTestReturnValue (10, Function)",
|
||||
func: function (count) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
window.PerfTestReturnValue(10);
|
||||
}
|
||||
},
|
||||
description: "Int argument, returns function value.",
|
||||
skipped: true,
|
||||
});
|
||||
// add more tests to queueTest
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Transparency Examples</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: Verdana, Arial;
|
||||
}
|
||||
img {
|
||||
opacity:0.4;
|
||||
}
|
||||
img:hover {
|
||||
opacity:1.0;
|
||||
}
|
||||
.box_white, .box_black {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
}
|
||||
.box_white {
|
||||
background-color: white;
|
||||
border: 2px solid black;
|
||||
color: black;
|
||||
}
|
||||
.box_black {
|
||||
background-color: black;
|
||||
border: 2px solid white;
|
||||
color: white;
|
||||
}
|
||||
.box_0 {
|
||||
opacity: 1.0;
|
||||
}
|
||||
.box_25 {
|
||||
opacity: 0.75;
|
||||
}
|
||||
.box_50 {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.box_75 {
|
||||
opacity: 0.25;
|
||||
}
|
||||
.box_100 {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Image Transparency</h1>
|
||||
Hover over an image to make it fully opaque.<br>
|
||||
<img src="http://www.w3schools.com/css/klematis.jpg" width="150" height="113" alt="klematis" />
|
||||
<img src="http://www.w3schools.com/css/klematis2.jpg" width="150" height="113" alt="klematis" />
|
||||
|
||||
<h1>Block Transparency</h1>
|
||||
<span class="box_white box_0">White 0%</span> <span class="box_white box_25">White 25%</span> <span class="box_white box_50">White 50%</span> <span class="box_white box_75">White 75%</span> <span class="box_white box_100">White 100%</span>
|
||||
<br>
|
||||
<span class="box_black box_0">Black 0%</span> <span class="box_black box_25">Black 25%</span> <span class="box_black box_50">Black 50%</span> <span class="box_black box_75">Black 75%</span> <span class="box_black box_100">Black 100%</span>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,27 @@
|
||||
<html>
|
||||
<body bgcolor="white">
|
||||
<script language="JavaScript">
|
||||
|
||||
// Send a query to the browser process.
|
||||
function execURLRequest() {
|
||||
document.getElementById('ta').value = 'Request pending...';
|
||||
|
||||
// Results in a call to the OnQuery method in urlrequest_test.cpp
|
||||
window.cefQuery({
|
||||
request: 'URLRequestTest:' + document.getElementById("url").value,
|
||||
onSuccess: function(response) {
|
||||
document.getElementById('ta').value = response;
|
||||
},
|
||||
onFailure: function(error_code, error_message) {
|
||||
document.getElementById('ta').value = 'Failed with error ' + error_message + ' (' + error_code + ')';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<form>
|
||||
URL: <input type="text" id="url" value="http://www.google.com">
|
||||
<br/><input type="button" onclick="execURLRequest();" value="Execute CefURLRequest">
|
||||
<br/><textarea rows="10" cols="40" id="ta"></textarea>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,48 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Window Test</title>
|
||||
<script>
|
||||
function send_message(test, params) {
|
||||
var message = 'WindowTest.' + test;
|
||||
if (typeof params != 'undefined')
|
||||
message += ':' + params;
|
||||
|
||||
// Results in a call to the OnQuery method in window_test.cpp.
|
||||
window.cefQuery({'request' : message});
|
||||
}
|
||||
|
||||
function minimize() {
|
||||
send_message('Minimize');
|
||||
}
|
||||
|
||||
function maximize() {
|
||||
send_message('Maximize');
|
||||
}
|
||||
|
||||
function restore() {
|
||||
minimize();
|
||||
setTimeout(function() { send_message('Restore'); }, 1000);
|
||||
}
|
||||
|
||||
function position() {
|
||||
var x = parseInt(document.getElementById('x').value);
|
||||
var y = parseInt(document.getElementById('y').value);
|
||||
var width = parseInt(document.getElementById('width').value);
|
||||
var height = parseInt(document.getElementById('height').value);
|
||||
if (isNaN(x) || isNaN(y) || isNaN(width) || isNaN(height))
|
||||
alert('Please specify a valid numeric value.');
|
||||
else
|
||||
send_message('Position', x + ',' + y + ',' + width + ',' + height);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<form>
|
||||
Click a button to perform the associated window action.
|
||||
<br/><input type="button" onclick="minimize();" value="Minimize">
|
||||
<br/><input type="button" onclick="maximize();" value="Maximize">
|
||||
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
|
||||
<br/><input type="button" onclick="position();" value="Set Position"> X: <input type="text" size="4" id="x" value="200"> Y: <input type="text" size="4" id="y" value="100"> Width: <input type="text" size="4" id="width" value="800"> Height: <input type="text" size="4" id="height" value="600">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,26 @@
|
||||
<html>
|
||||
<body bgcolor="white">
|
||||
<script language="JavaScript">
|
||||
function execXMLHttpRequest()
|
||||
{
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", document.getElementById("url").value, true);
|
||||
xhr.setRequestHeader('My-Custom-Header', 'Some Value');
|
||||
xhr.onload = function(e) {
|
||||
if (xhr.readyState === 4) {
|
||||
var value = "Status Code: "+xhr.status;
|
||||
if (xhr.status === 200)
|
||||
value += "\n\n"+xhr.responseText;
|
||||
document.getElementById('ta').value = value;
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
</script>
|
||||
<form>
|
||||
URL: <input type="text" id="url" value="http://tests/request">
|
||||
<br/><input type="button" onclick="execXMLHttpRequest();" value="Execute XMLHttpRequest">
|
||||
<br/><textarea rows="10" cols="40" id="ta"></textarea>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This is a low level implementation of atomic semantics for reference
|
||||
// counting. Please use cef_ref_counted.h directly instead.
|
||||
//
|
||||
// The Chromium implementation includes annotations to avoid some false
|
||||
// positives when using data race detection tools. Annotations are not
|
||||
// currently supported by the CEF implementation.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_ATOMIC_REF_COUNT_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/atomic_ref_count.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include "include/base/cef_atomicops.h"
|
||||
|
||||
// Annotations are not currently supported.
|
||||
#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
|
||||
#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
|
||||
|
||||
namespace base {
|
||||
|
||||
typedef subtle::Atomic32 AtomicRefCount;
|
||||
|
||||
// Increment a reference count by "increment", which must exceed 0.
|
||||
inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
|
||||
AtomicRefCount increment) {
|
||||
subtle::NoBarrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
// Decrement a reference count by "decrement", which must exceed 0,
|
||||
// and return whether the result is non-zero.
|
||||
// Insert barriers to ensure that state written before the reference count
|
||||
// became zero will be visible to a thread that has just made the count zero.
|
||||
inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
|
||||
AtomicRefCount decrement) {
|
||||
ANNOTATE_HAPPENS_BEFORE(ptr);
|
||||
bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
|
||||
if (!res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Increment a reference count by 1.
|
||||
inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
|
||||
base::AtomicRefCountIncN(ptr, 1);
|
||||
}
|
||||
|
||||
// Decrement a reference count by 1 and return whether the result is non-zero.
|
||||
// Insert barriers to ensure that state written before the reference count
|
||||
// became zero will be visible to a thread that has just made the count zero.
|
||||
inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
|
||||
return base::AtomicRefCountDecN(ptr, 1);
|
||||
}
|
||||
|
||||
// Return whether the reference count is one. If the reference count is used
|
||||
// in the conventional way, a refrerence count of 1 implies that the current
|
||||
// thread owns the reference and no other thread shares it. This call performs
|
||||
// the test for a reference count of one, and performs the memory barrier
|
||||
// needed for the owning thread to act on the object, knowing that it has
|
||||
// exclusive access to the object.
|
||||
inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
|
||||
bool res = (subtle::Acquire_Load(ptr) == 1);
|
||||
if (res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Return whether the reference count is zero. With conventional object
|
||||
// referencing counting, the object will be destroyed, so the reference count
|
||||
// should never be zero. Hence this is generally used for a debug check.
|
||||
inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
|
||||
bool res = (subtle::Acquire_Load(ptr) == 0);
|
||||
if (res) {
|
||||
ANNOTATE_HAPPENS_AFTER(ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
|
||||
@ -0,0 +1,198 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// For atomic operations on reference counts, see cef_atomic_ref_count.h.
|
||||
|
||||
// The routines exported by this module are subtle. If you use them, even if
|
||||
// you get the code right, it will depend on careful reasoning about atomicity
|
||||
// and memory ordering; it will be less readable, and harder to maintain. If
|
||||
// you plan to use these routines, you should have a good reason, such as solid
|
||||
// evidence that performance would otherwise suffer, or there being no
|
||||
// alternative. You should assume only properties explicitly guaranteed by the
|
||||
// specifications in this file. You are almost certainly _not_ writing code
|
||||
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
|
||||
// implementations on other archtectures will cause your code to break. If you
|
||||
// do not know what you are doing, avoid these routines, and use a Mutex.
|
||||
//
|
||||
// It is incorrect to make direct assignments to/from an atomic variable.
|
||||
// You should use one of the Load or Store routines. The NoBarrier
|
||||
// versions are provided when no barriers are needed:
|
||||
// NoBarrier_Store()
|
||||
// NoBarrier_Load()
|
||||
// Although there are currently no compiler enforcement, you are encouraged
|
||||
// to use these.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BASE_ATOMICOPS_H_)
|
||||
// Do nothing if the Chromium header has already been included.
|
||||
// This can happen in cases where Chromium code is used directly by the
|
||||
// client application. When using Chromium code directly always include
|
||||
// the Chromium header first to avoid type conflicts.
|
||||
#elif defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/atomicops.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
|
||||
// windows.h #defines this (only on x64). This causes problems because the
|
||||
// public API also uses MemoryBarrier at the public name for this fence. So, on
|
||||
// X64, undef it, and call its documented
|
||||
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
|
||||
// implementation directly.
|
||||
#undef MemoryBarrier
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
typedef int32_t Atomic32;
|
||||
#ifdef ARCH_CPU_64_BITS
|
||||
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
|
||||
// means Atomic64 and AtomicWord should be the same type on 64-bit.
|
||||
#if defined(__ILP32__) || defined(OS_NACL)
|
||||
// NaCl's intptr_t is not actually 64-bits on 64-bit!
|
||||
// http://code.google.com/p/nativeclient/issues/detail?id=1162
|
||||
typedef int64_t Atomic64;
|
||||
#else
|
||||
typedef intptr_t Atomic64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
|
||||
// Atomic64 routines below, depending on your architecture.
|
||||
typedef intptr_t AtomicWord;
|
||||
|
||||
// Atomically execute:
|
||||
// result = *ptr;
|
||||
// if (*ptr == old_value)
|
||||
// *ptr = new_value;
|
||||
// return result;
|
||||
//
|
||||
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
|
||||
// Always return the old value of "*ptr"
|
||||
//
|
||||
// This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
// Atomically store new_value into *ptr, returning the previous value held in
|
||||
// *ptr. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
|
||||
|
||||
// Atomically increment *ptr by "increment". Returns the new value of
|
||||
// *ptr with the increment applied. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
|
||||
|
||||
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment);
|
||||
|
||||
// These following lower-level operations are typically useful only to people
|
||||
// implementing higher-level synchronization operations like spinlocks,
|
||||
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
|
||||
// a store with appropriate memory-ordering instructions. "Acquire" operations
|
||||
// ensure that no later memory access can be reordered ahead of the operation.
|
||||
// "Release" operations ensure that no previous memory access can be reordered
|
||||
// after the operation. "Barrier" operations have both "Acquire" and "Release"
|
||||
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
|
||||
// access.
|
||||
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
void MemoryBarrier();
|
||||
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
|
||||
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Release_Load(volatile const Atomic32* ptr);
|
||||
|
||||
// 64-bit atomic operations (only available on 64-bit processors).
|
||||
#ifdef ARCH_CPU_64_BITS
|
||||
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
|
||||
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Release_Load(volatile const Atomic64* ptr);
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
} // namespace subtle
|
||||
} // namespace base
|
||||
|
||||
// Include our platform specific implementation.
|
||||
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
#include "include/base/internal/cef_atomicops_x86_msvc.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "include/base/internal/cef_atomicops_mac.h"
|
||||
#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
#include "include/base/internal/cef_atomicops_x86_gcc.h"
|
||||
#else
|
||||
#error "Atomic operations are not supported on your platform"
|
||||
#endif
|
||||
|
||||
// On some platforms we need additional declarations to make
|
||||
// AtomicWord compatible with our other Atomic* types.
|
||||
#if defined(OS_MACOSX) || defined(OS_OPENBSD)
|
||||
#include "include/base/internal/cef_atomicops_atomicword_compat.h"
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
|
||||
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
|
||||
// Google Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
||||
#define CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
// When building CEF include the Chromium header directly.
|
||||
#include "base/basictypes.h"
|
||||
#else // !BUILDING_CEF_SHARED
|
||||
// The following is substantially similar to the Chromium implementation.
|
||||
// If the Chromium implementation diverges the below implementation should be
|
||||
// updated to match.
|
||||
|
||||
#include <limits.h> // For UINT_MAX
|
||||
#include <stddef.h> // For size_t
|
||||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
// The NSPR system headers define 64-bit as |long| when possible, except on
|
||||
// Mac OS X. In order to not have typedef mismatches, we do the same on LP64.
|
||||
//
|
||||
// On Mac OS X, |long long| is used for 64-bit types for compatibility with
|
||||
// <inttypes.h> format macros even in the LP64 model.
|
||||
#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
|
||||
typedef long int64; // NOLINT(runtime/int)
|
||||
typedef unsigned long uint64; // NOLINT(runtime/int)
|
||||
#else
|
||||
typedef long long int64; // NOLINT(runtime/int)
|
||||
typedef unsigned long long uint64; // NOLINT(runtime/int)
|
||||
#endif
|
||||
|
||||
// TODO: Remove these type guards. These are to avoid conflicts with
|
||||
// obsolete/protypes.h in the Gecko SDK.
|
||||
#ifndef _INT32
|
||||
#define _INT32
|
||||
typedef int int32;
|
||||
#endif
|
||||
|
||||
// TODO: Remove these type guards. These are to avoid conflicts with
|
||||
// obsolete/protypes.h in the Gecko SDK.
|
||||
#ifndef _UINT32
|
||||
#define _UINT32
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
|
||||
#endif // !BUILDING_CEF_SHARED
|
||||
|
||||
// UTF-16 character type.
|
||||
// This should be kept synchronized with base/strings/string16.h
|
||||
#ifndef char16
|
||||
#if defined(WCHAR_T_IS_UTF16)
|
||||
typedef wchar_t char16;
|
||||
#elif defined(WCHAR_T_IS_UTF32)
|
||||
typedef unsigned short char16;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user